Don’t mix Doctrine Annotations and PHP8 Attributes

When working on an older project I came around a strange behavior, which took me some time to debug. I got the error „App\Document\OldDocument is not a valid entity or mapped super class.“ To summarize: don’t mix PHP8 Attributes and Doctrine Annotations in one project!

I wanted to extend an old project by some new MongoDB Documents. Since I updated the project already to PHP8, I wanted to start using PHP8 Attributes for my new Documents. But I didn’t want to spend the time to refactor all existing MongoDB ODM Documents and migrate them from Doctrine Annotations to PHP8 Attributes.

Difference between Doctrine Annotations and PHP 8 Attributes

For everyone, who does not yet know the difference, here is a very quick explanation. Before PHP8, the PHP programming language did not know any way to give hints or options about the following source code. As a workaround, Doctrine used PHP Docblock Comments to e.g. define which type a Database field should have. These Comments are called Annotations.

Here is an example of a Doctrine MongoDB ODM document using Annotations:

<?php
namespace App\Document;

use Doctrine\ODM\MongoDB\Mapping\Annotations as MongoDB;

/**
 * * @MongoDB\Document
 */
class MyDocument
{
    /**
     * @MongoDB\Id 
     */
    protected string $id;

    /**
     * @MongoDB\Field(type="string") 
     */
    protected string $title;
}

Because development relied more and more on Annotations, which were not standardized yet, PHP introduced the concept of Attributes with the version PHP8. Attributes work pretty similar to Doctrine Annotations, but using a slightly different syntax.

For backwards compatibility, they also start out as PHP comment. But the use the # symbol for one line comments in PHP. Here is the same example as before, but with PHP8 Attributes.

<?php
namespace App\Document;

use Doctrine\ODM\MongoDB\Mapping\Annotations as MongoDB;
use Doctrine\ODM\MongoDB\Types\Type;

#[MongoDB\Document]
class MyDocument
{
    #[MongoDB\Id]
    protected string $id;

    #[MongoDB\Field(type: Type::STRING)]
    protected string $title;
}

Since PHP8 Attributes are often one-liners, the resulting code appears a little shorter. But be aware of the second use statement!

Error when mixing Doctrine Annotations and PHP8 Attributes in Symfony

So, back to my problem. After creating a new Doctrine ODM Document with PHP8 Attributes in my old project, I suddenly got the following error:

"App\Document\OldDocument is not a valid entity or mapped super class."

The new Documents were working fine, but Doctrine were always complaining that my existing Documents were not valid. But I did not even touch the source of the old Documents.

After I little testing, I found out, that apparently, you can not mix Doctrine Annotations and PHP8 Documents for Document declaration in one Symfony project.

So, there are two solutions to this problem:

  1. Stay with Doctrine Annotations on existing projects if you do only some small changes or extensions.
  2. Do all the work and migrate every single last Document from Doctrine Annotations to PHP8 Attributes

Schreiben Sie einen Kommentar