【问题标题】:Trouble with importing annotations导入注释的问题
【发布时间】:2012-08-08 06:09:18
【问题描述】:

我正在开发一个 CodeIgniter 项目,在该项目中我使用了 Doctrine2 和 Symfony2 Validator 组件。

我所有的 Doctrine2 实体 use Doctrine\ORM\Mapping 和实体管理器都识别它们。我的实体注释如下所示:

/**
 * @Entity(repositoryClass = "UserRepository")
 * @Table(name = "user")
 * @HasLifecycleCallbacks()
 */

此时,我可以毫无问题地持久化实体。第一个问题出现在我尝试使用 Symfony2 Validator 组件时。当我尝试验证 User 对象时,我收到此错误:

[语义错误] Entity\User 类中的注释“@Entity”从未被导入。您是否可能忘记为此注释添加“使用”语句?

此问题的唯一“修复”是通过use Doctrine\Mapping\Entity,但我必须为我的实体(表、列、ManyToOne 等)使用的每个注释执行此操作。我试图弄清楚为什么我需要明确地 use 每个注释类而不是自动识别它们(use Doctrine\ORM\Mapping 不应该授予我对该命名空间内所有类的访问权限吗?)。

然后,我尝试使用use Doctrine\ORM\Mapping as ORM 并在所有注释前加上ORM\。例如:@ORM\Entity()。 Symfony2 验证器停止抱怨,但现在 Doctrine2 抱怨 Class Entity\User is not a valid entity or mapped super class. 我不知道为什么这种方法适用于验证器,但不适用于 Doctrine2。如果我运行控制台命令doctrine:orm:info,我的User 实体将无法识别。

因为这是一个 CodeIgniter 应用程序,所以我正在自动加载 Symfony2 和 Doctrine2 库。我的自动加载代码如下:

# Symfony2 ClassLoader component
require_once __DIR__ . '/application/libraries/symfony/src/Symfony/Component/ClassLoader/UniversalClassLoader.php';
$loader = new \Symfony\Component\ClassLoader\UniversalClassLoader();
$loader->register();
$loader->registerNamespace('Symfony', __DIR__ . '/application/libraries/symfony/src');
$loader->registerNamespace('Doctrine', __DIR__ . '/application/libraries/doctrine/lib');

# Doctrine2 
require_once __DIR__ . '/application/libraries/doctrine/lib/Doctrine/Common/Annotations/AnnotationRegistry.php';
use Doctrine\Common\Annotations\AnnotationRegistry;
AnnotationRegistry::registerLoader(function($class) use ($loader) {
    $loader->loadClass($class);
    $classExists = class_exists($class, false);
    return $classExists;
});
AnnotationRegistry::registerFile(__DIR__ . '/application/libraries/doctrine/lib/Doctrine/ORM/Mapping/Driver/DoctrineAnnotations.php');

我不在乎是否必须以 ORM\ 开头,我只想找到一个 Symfony2 Validator 和 Doctrine2 都可以使用的解决方案。有什么想法吗?

【问题讨论】:

    标签: php doctrine-orm


    【解决方案1】:

    我在使用 Silex、Doctrine2 和 Symfony-Validator 时遇到了类似的问题。

    解决方案是避免使用 SimpleAnnotationsReader,而是使用普通的 AnnotationReader(查看Doctrine\ORM\Configuration::newDefaultAnnotationDriver)。然后,您可以在每个实体前面加上 ORM\(当然,在每个实体中插入 use Doctrine\ORM\Mapping as ORM;)。

    【讨论】:

    • 如果它在没有 ORM\ 的情况下工作,所以我们以这种方式编码每个实体,现在它突然无缘无故停止工作,我们留下了维护的噩梦?class="comcopy">跨度>
    • 只是为了回答 Brandon 的问题并节省其他人自己发现问题的时间:如果您的代码库使用 Doctrine 注释而不导入 Doctrine\ORM\Mapping 命名空间,那么您已与 Doctrine 的 SimpleAnnotationReader 结婚,这意味着你不能只是开始使用命名空间导入的注解并逐步重构你的代码。好吧,至少在不破解 AnnotationReader 的情况下(这是解析 use 语句的那个​​)。
    【解决方案2】:

    我通过将以下内容添加到我的实体文件中解决了这个问题:

    use Doctrine\ORM\Mapping as ORM;
    

    所以我的文件现在看起来像:

    <?php
    
    namespace Acme\CustomBundle\Entity;
    
    use Doctrine\ORM\Mapping as ORM;
    
    /**
     * Example
     *
     * @ORM\Entity
     * @ORM\Table(name="example")
     *
     */
    class Example
    {
        /**
         * @ORM\Column(type="integer")
         * @ORM\Id
         * @ORM\GeneratedValue(strategy="AUTO")
         *
         * @var integer
         */
        private $id;
    
        /**
         * @ORM\Column(type="string", length=125)
         *
         * @var string
         */
        private $title;
    
        /**
         * Get id
         *
         * @return integer
         */
        public function getId()
        {
            return $this->id;
        }
    
        /**
         * Set title
         *
         * @param string $title
         *
         * @return Example
         */
        public function setTitle($title)
        {
            $this->title = $title;
    
            return $this;
        }
    
        /**
         * Get title
         *
         * @return string
         */
        public function gettitle()
        {
            return $this->title;
        }
    
    }
    

    【讨论】:

    【解决方案3】:

    添加use 语句 您在entities 中使用的每个注释。例如:

    use Doctrine\ORM\Mapping\Entity;
    use Doctrine\ORM\Mapping\Table;
    use Doctrine\ORM\Mapping\Id;
    use Doctrine\ORM\Mapping\Column;
    use Doctrine\ORM\Mapping\GeneratedValue;
    

    但您可能对使用此方法不感兴趣。您可以将所有use 语句写入一个文件,然后将其包含在您的entities 中。

    【讨论】:

    • use Doctrine\ORM\Mapping as ORM; 允许您使用@ORM\Entity 等,这更加简洁。 user1825294 说得对。
    • 这不是您想要的解决方案!注释也不会有什么。
    【解决方案4】:

    我收到了相同的错误消息“[Semantical Error] Entity\User 类中的注释“@Entity”从未导入。您可能忘记为此注释添加“use”语句吗?”。

    问题是我有 ORM 的别名并且没有将它用于注释。

    我有这个:@OneToOne(targetEntity="CompanyProduct")

    正确的是:@ORM\OneToOne(targetEntity="CompanyProduct")

    【讨论】:

      【解决方案5】:

      如果您正在测试并且您的测试因此而失败。确保在 phpunit 设置中配置了正确的自动加载。

      对于一个非常具体的场景,我的问题是升级我的 symfony 版本,而在我拥有 bootstrap.cache.php 文件之前,但在新版本上,它是 app/autoload。我不得不更改我的phpunit.xml 配置文件并将我的引导选项设置为该文件bootstrap="autoload.php"

      【讨论】:

        【解决方案6】:

        我的问题通过添加解决了:

        use Doctrine\ORM\Mapping\HasLifecycleCallbacks;

        【讨论】:

          【解决方案7】:

          丑陋的解决方案

          我正在学习学说,在这个阶段对我来说重要的是我可以轻松地从网站上复制/粘贴示例并使用它们而无需额外的编辑。

          • 为所有实体设置这样的命名空间:namespace Doctrine\ORM\Mapping;

          【讨论】:

            猜你喜欢
            • 2017-12-03
            • 1970-01-01
            • 2011-09-29
            • 2012-06-10
            • 1970-01-01
            • 1970-01-01
            • 2014-04-12
            • 1970-01-01
            • 2015-03-28
            相关资源
            最近更新 更多