Symfony2: Annotations get better
May 23, 2011 • Published by Fabien Potencier
Later today, I will release Symfony2 beta2. But first, I wanted to talk about a big change that landed into master yesterday. As you might know, Symfony2 uses annotations for Doctrine mapping information and validation configuration. Of course, it is entirely optional, and the same can be done with XML, YAML, or even PHP. But using annotations is convenient and allows you to define everything in the same file.
Symfony Standard Edition provides an even better support for annotations via
two additional bundles: SensioFrameworkExtraBundle
and
JMSSecurityExtraBundle
. They allow you to use annotations for controller
configuration (routing, cache, security, template, ...).
To avoid ambiguities when different libraries/bundles define new annotations, you were required to use a configurable "prefix":
/**
* @orm:Entity
*/
class User
{
/**
* @orm:Column(type="string", nullable=false)
* @assert:NotBlank
*/
private $name;
}
But several problems arose quite fast:
If you have a look at the Doctrine documentation, you will see that
@Column
is used instead of@orm:Column
. That's because the prefix is optional. So, the Doctrine documentation does not use one, but Symfony2 forces you to useorm
. Note that it is configurable, so you might use any other prefix (@doctrine:Column
).The annotation library did not play well with autoloading.
SensioFrameworkExtraBundle
andJMSSecurityExtraBundle
shared the sameextra
prefix, but it was a hack and it was not really scalable.
Johannes worked hard in the last few weeks to find an elegant solution to this problem. As each annotation is defined as a class, instead of using only the short class name, we have decided to use the fully qualified class name. It removes the need for arbitrary prefixes defined as a global configuration, avoids any ambiguities between libraries, and gets rid of the autoloading issue altogether:
/**
* @Doctrine\ORM\Mapping\Entity
*/
class User
{
/**
* @Doctrine\ORM\Mapping\Column(type="string", nullable=false)
* @Symfony\Component\Validator\Constraints\NotBlank
*/
private $name;
}
Of course, using the FQCN everywhere is quite verbose but fortunately, PHP
already has a solution via the use
statement:
use Doctrine\ORM\Mapping as ORM;
use Symfony\Component\Validator\Constraints as Assert;
/**
* @ORM\Entity
*/
class User
{
/**
* @ORM\Column(type="string", nullable=false)
* @Assert\NotBlank
*/
private $name;
}
Annotations now feel more "native". If you want to use annotations outside of a Symfony2 context, have a look at the Doctrine Common repository (version 3.0).
Help the Symfony project!
As with any Open-Source project, contributing code or documentation is the most common way to help, but we also have a wide range of sponsoring opportunities.
Comments are closed.
To ensure that comments stay relevant, they are closed for old posts.
Just to make it clear, this means that Symfony2 stable will come with Doctrine Common 3.x which is scheduled to be released end of June.
It's a little more code to write (and to remember!) but I see that this is necessary in the "big picture". Thanks for your hard work, I really begin to enjoy Symfony2 and I'm looking forward for the final release.
It's both easy and configurable. Great job, Johannes!
Can't help but feel there is a Lot more typing in SF2...
And still no default= option?!
Someone pointed me out that special characters in tag names might be and issue for DocBlock parsers.
Someone tried generating a documentation with such annotations included?
We will port this back to Doctrine 2.1 aswell, we already have a working implementation that has this features and is backwards compatible (i.e. allows to set @alias: aswell).
We havent discussed finally what features become deprecated and which will make the step to 3.0
Totally awesome! Great work Johannes
Looks great..
Although I've saw its now called 'Symfony Standard Edition'.
Please please please please please tell me that symfony isn't going to have a 'standard' and 'premium' edition...
The changes above can have influence on applications which parse DocBlocks as tag names are commonly defined as being alphanumeric.
I'd expect that parsers can adapt (except for perhaps the older ones) but a detailed specification of the new format is necessary. I know I wouldn't mind adapting DocBlox but I'd need the spec.
The format above also conflicts with efforts in Internals where a different format is proposed for a similar functionality. Perhaps you and Guillhermo can work together to come to a single standard?
I really like this and It improves the understanding of what is going on under the hood. Great job!
@Mike, Guilherme was also involved in the process of updating Doctrine Common to this new approach. We basically follow the EBNF that is detailed in Guilherme's first RFC with the exception that we do not use "<>" but "@" to mark annotations (https://wiki.php.net/rfc/annotations).
@Johannes: Guillhermo has written a new RFC (https://wiki.php.net/rfc/annotations-in-docblock) which differs from the format presented above.
For one it does not mention the use of non-alphanumeric character as tag names.
And additionally it present that content in the 'description' section of the tag; whilst the above code shows no space between the @tagname and the (content). This does not help when generating documentation as a tag is no longer an identifier but now has contextual meaning and thus countless variations.
@Jon Busby: there will not be a "premium" edition in case you are worried about a close source commercial edition. The purpose of the editions is to convey the idea that you can have many versions of the framework.
For example there could be a "Rest Server Edition" or a "CMF Edition" that come preconfigured with relevant Bundles, libs and settings.
Namespaced annotations, Less wtf's..
Awesome idea =)
Very nice feature. It would be cool if the reflection API supports a ReflectionNamespace class, to query this use statements.
Is there anyone with C and PHP internal skills, who can implement this missing feature, so that it can be merged into PHP5.4!?