orm: [BUG] Semantic Error on annotations after upgrading to Laravel 9

Package version, Laravel version

Laravel 9

beberlei/doctrineextensions                    v1.3.0
doctrine/annotations                           1.14.2
doctrine/cache                                 1.13.0
doctrine/collections                           1.8.0
doctrine/common                                3.4.3
doctrine/data-fixtures                         1.6.3
doctrine/dbal                                  2.13.9
doctrine/deprecations                          v0.5.3
doctrine/event-manager                         1.2.0
doctrine/inflector                             2.0.6
doctrine/instantiator                          1.5.0
doctrine/lexer                                 1.2.3
doctrine/migrations                            3.4.2
doctrine/orm                                   2.14.0
doctrine/persistence                           2.5.6
gedmo/doctrine-extensions                      v3.10.0
laravel-doctrine/extensions                    1.5.1
laravel-doctrine/migrations                    3.x-dev b096637
laravel-doctrine/orm                           1.8.1
ramsey/uuid-doctrine                           1.8.2

PHP Version:

PHP 8.1.14 (cli) (built: Jan  6 2023 15:22:56) (NTS)
Copyright (c) The PHP Group
Zend Engine v4.1.14, Copyright (c) Zend Technologies
    with Zend OPcache v8.1.14, Copyright (c), by Zend Technologies
    with Xdebug v3.2.0, Copyright (c) 2002-2022, by Derick Rethans

Expected behaviour

It was working on Laravel 8

Actual behaviour

When I run anything related to Entities, I am getting this error: Doctrine\Common\Annotations\AnnotationException : [Semantical Error] The annotation "@Doctrine\ORM\Mapping\Entity" in class App\Domain\Models\Identity\User was never imported. Did you maybe forget to add a "use" statement for this annotation?

For example php artisan doctrine:info

Steps to reproduce the behaviour

My Entity looks like:

<?php

declare(strict_types=1);

namespace App\Domain\Models\Identity;

use App;
use App\Domain\Entity;
use Doctrine\ORM\Mapping as ORM;
use Gedmo\Mapping\Annotation as Gedmo;
use Illuminate\Auth\Authenticatable;
use Illuminate\Contracts\Auth\Authenticatable as AuthenticatableContract;
use Ramsey\Uuid\UuidInterface;

/**
 * @ORM\Entity
 * @ORM\Table(
 *     name="users",
 *     indexes={
 *         @ORM\Index(name="idx_email", columns={"email"}),
 *         @ORM\Index(name="idx_type", columns={"type"}),
 *     },
 * )
 * @Gedmo\Loggable
 */
class User extends Entity implements AuthenticatableContract
{
    use Authenticatable;

    /**
     * @ORM\Id
     * @ORM\Column(type="uuid_binary")
     */
    protected UuidInterface $id;
    /**
     * @Gedmo\Versioned
     * @ORM\Column(type="string")
     */
    protected string $email;
    /**
     * @Gedmo\Versioned
     * @ORM\Column(type="string")
     */
    protected string $type;

    public function id(): UuidInterface
    {
        return $this->id;
    }
}

About this issue

  • Original URL
  • State: closed
  • Created a year ago
  • Comments: 24 (18 by maintainers)

Most upvoted comments

I have released new versions for both extensions and acl libs. Please see if that fixes it for you.

Confirming its working for me too.

Thanks @eigan

It looks like it’s working now! 😍

@eigan Works for me 🫶

beberlei/doctrineextensions        v1.3.0         
doctrine/annotations               1.14.2         
doctrine/cache                     1.13.0         
doctrine/collections               1.8.0          
doctrine/common                    3.4.3          
doctrine/dbal                      2.13.9         
doctrine/deprecations              v0.5.3         
doctrine/event-manager             1.2.0          
doctrine/inflector                 2.0.6          
doctrine/instantiator              1.5.0          
doctrine/lexer                     1.2.3          
doctrine/migrations                3.4.2          
doctrine/orm                       2.14.0         
doctrine/persistence               2.5.6          
gedmo/doctrine-extensions          v3.10.0        
laravel-doctrine/acl               1.6.1          
laravel-doctrine/extensions        1.5.2          
laravel-doctrine/migrations        3.x-dev b096637
laravel-doctrine/orm               1.8.1          

An easier solution would be to just add class_exists loader like this:

AnnotationRegistry::registerLoader('class_exists');

This can replace your loader @whizzrd.

we use AnnotationRegistry::registerLoader in laravel-doctrine/acl/src/AclServiceProvider.php so I’m sure ACL is also to be effected by the changes in doctrine/annotations

Confirming the solution proposed by @whizzrd did solve the problem.

Thank you Joris.

@dpslwk what could you suggest to me for now? Can I use PHP8 annotations instead of doc-blocks? Or I can use YAML/XML mappings? I should upgrade the project to Laravel 9, so I am searching the possible solutions

I ran into the same problem recently and worked around it by providing my own loader

\App\Providers\AnnotationsServiceProvider::register


        AnnotationRegistry::registerLoader([
            new DoctrineAnnotationLoader(),
            'loadClass',
        ]);
        AnnotationRegistry::loadAnnotationClass(Entity::class);

\App\Doctrine\Mappings\DoctrineAnnotationLoader

namespace App\Doctrine\Mappings;

/**
 * Autoloader for Doctrine Annotations
 * @note This should not be necessary
 * @deprecated Laravel-Doctrine _should_ provide autoloading at some point
 */
class DoctrineAnnotationLoader
{
    /**
     * @const
     */
    const ANNOTATION_NAMESPACE = 'Doctrine\\ORM\\Mapping\\';

    /**
     * @const
     */
    const ANNOTATION_PATH = 'vendor/doctrine/orm/lib/Doctrine/ORM/Mapping/';

    /**
     * @param $class
     *
     * @return mixed
     */
    public function loadClass($class)
    {
        if (strpos($class, self::ANNOTATION_NAMESPACE) === 0) {
            $class = str_replace(self::ANNOTATION_NAMESPACE, '', $class);

            $file = base_path(self::ANNOTATION_PATH) . $class . '.php';
            if (file_exists($file)) {
                require_once $file;

                return true;
            }
        }
    }
}