Symfony2 Doctrine为不同的bundle找不到映射的超类注释

时间:2016-11-07 16:57:34

标签: doctrine-orm annotations doctrine symfony

Symfony 2.8 + doctrine

我有两个套装:CoreBundleBonusBundle

CoreBundle包含包含 abstract ClassA的文件夹模型:

use Doctrine\ORM\Mapping as ORM;
//[...]

abstract class ClassA
{

    /**
     * @var string
     *
     * @ORM\Column(name="name", type="string", length=255)
     */
    protected $name;
}

并在另一个目录中实体 - ClassB

//[...]
/**
 * ClassB
 *
 * @ORM\Table()
 * @ORM\Entity
 */
class ClassB extends ClassA
{
    /**
     * @var integer
     *
     * @ORM\Column(name="id", type="integer")
     * @ORM\Id
     * @ORM\GeneratedValue(strategy="AUTO")
     */
    private $id;

}

目前运行良好,ClassB继承了name属性,这样我们就将实体ClassBidname进行了映射。

我在BonusBundle(第二个)其他抽象类ClassC的模型目录中添加了。它与ClassA相同,但在其他捆绑中。

现在最后一个重点是我的例子 - 我在ClassD(实体目录)中添加了CoreBundle,从BonusBundle扩展了ClassC(与上面相同)。

我的问题

在结果中,我使用属性idname和仅具有id属性的ClassD重新获得了ClassB。

我无法理解为什么会这样。如果超类存在于其他Bundle中,它看起来像doctrine忽略注释。我检查了一些文档和其他问题,但我无法理解发生了什么。 I see in config docs here auto_mapping选项检查实体目录:

  

Doctrine的auto_mapping功能从中加载注释配置   每个包的实体/目录并查找其他格式(例如   资源/ config / doctrine目录中的YAML,XML。

  

如果无法确定a的配置格式   捆绑,DoctrineBundle将检查是否有Entity文件夹   捆绑包的根目录。如果该文件夹存在,Doctrine将会失败   回到使用注释驱动程序。

在我的项目中,此文件夹同时存在于Bundles中。如果symfony只检查Entity文件夹那么为什么第一个例子(Model)运行良好? 这种机制如何运作?

2 个答案:

答案 0 :(得分:3)

我测试了一些可能性,我找到了修复它的解决方案,但仍然不知道为什么会发生这种情况。

如果我向超类@ORM\MappedSuperclass()添加注释,则只有当类位于Entity目录中时才会正确加载映射。

use Doctrine\ORM\Mapping as ORM;

/**
 * ClassA
 *
 * @ORM\MappedSuperclass()
 */
abstract class ClassA
{
    /**
     * @var string
     *
     * @ORM\Column(name="name", type="string", length=255)
     */
    protected $name;
}

这样,我的注释在其他Bundles中可见,而我的ClassA本身不是Entity

仍然我不明白为什么它可以工作如果类存在于同一个Bundle但在其他目录中。另外在FoSUserBundle内部存在使用MappedSuperclass() - FOSUserBundle/Model/User.php的类似示例,但它位于Model目录中并且仍在工作。

<强> //修改

完成@Boulzy回答

可能我找到第二部分的答案 - 为什么它可以看到来自其他目录的映射但是相同的捆绑。在分析了其他工作示例后,我发现具有严格访问private的映射属性对于子类是不可见的,但protected属性是可见的,映射的并且不需要@ORM\MappedSuperclass()注释因为它在同一Bundle中使用。

似乎@ORM\MappedSuperclass()使我们有可能映射甚至private属性,这样它们可见并映射到任何其他包中的其他类(只要它存在于Entity或其他映射目录中) )。

答案 1 :(得分:2)

在完成@Griva关于MappedSuperClass的回答时,这是一个简单的例子,说明如何告诉Doctrine在实体以外的其他文件夹中查找映射类:

<?php

    namespace AppBundle;

    use Doctrine\Bundle\DoctrineBundle\DependencyInjection\Compiler\DoctrineOrmMappingsPass;
    use Symfony\Component\DependencyInjection\ContainerBuilder;
    use Symfony\Component\HttpKernel\Bundle\Bundle;

    class AppBundle extends Bundle
    {
        /**
         * {@inheritDoc}
         */
        public function build(ContainerBuilder $container)
        {
            parent::build($container);

            // With Yaml configuration format
            $container->addCompilerPass(DoctrineOrmMappingsPass::createYamlMappingDriver(array(
                realpath(__DIR__ . '/Resources/config/doctrine-mapping') => 'AppBundle\Model'
            )));

            // With annotation configuration format
            $container->addCompilerPass(DoctrineOrmMappingsPass::createAnnotationMappingDriver(array(
                'AppBundle\Model'
            )));
        }
    }

MongoDB和CouchDB也有Doctrine MappingsPass。