Symfony 2.8 + doctrine
我有两个套装:CoreBundle
和BonusBundle
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
属性,这样我们就将实体ClassB
与id
和name
进行了映射。
我在BonusBundle
(第二个)其他抽象类ClassC
的模型目录中添加了。它与ClassA相同,但在其他捆绑中。
现在最后一个重点是我的例子 - 我在ClassD
(实体目录)中添加了CoreBundle
,从BonusBundle
扩展了ClassC(与上面相同)。
在结果中,我使用属性id
,name
和仅具有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)运行良好?
这种机制如何运作?
答案 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。