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 use orm. Note that it is configurable, so you might use any other prefix (@doctrine:Column).

  • The annotation library did not play well with autoloading.

  • SensioFrameworkExtraBundle and JMSSecurityExtraBundle shared the same extra 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).

Published in #Living on the edge