doctrine加载相关的继承对象

时间:2014-04-01 21:43:30

标签: symfony doctrine-orm

问题:如何使用与doctrine一起使用继承映射的关联对象加载对象?

例如使用这些对象: (忽略拼写错误,我从我的真实示例代码中重命名了一些东西)

/**
 * @ORM\Table(name="int_entity")
 * @ORM\Entity
 * })
 */
class IntEntity extends BaseEntity
{
    /**
     * @ORM\Column(name="int_value", type="integer", nullable=true)
    **/
    public $intValue;
}

/**
     * @ORM\Table(name="float_entity")
     * @ORM\Entity
     * })
     */
    class floatEntity extends FakeBaseMixedEntity
    {   
        /**
         * @ORM\Column(name="float_value", type="float", nullable=true)
        **/
        public $floatValue;
    }

/** @ORM\MappedSuperclass */
class BaseEntity
{
    /**
     * @ORM\Column(name="id", type="integer")
     * @ORM\Id
     */
    private $id;

    //could be other variables I guess but I didn't need any. The point of the
    //base class in my case is more of an interface I guess...
}

 /**
     * @ORM\Table(name="Entity_Containing_Inherited_Entity")
     * @ORM\Entity
     * })
     */
    class EntityContainingInheritedEntity
    {
        /**
         * @ORM\Column(name="id", type="integer")
         * @ORM\Id
         * @ORM\GeneratedValue(strategy="IDENTITY") 
         */
        public $id;

        /**
         * @ORM\Column(name="string_value", type="string")  
         */
        public $stringValue;

        /**
        * @ORM\OneToOne(targetEntity="BaseEntity", cascade={"persist"})
        * @ORM\JoinColumn(name="id", referencedColumnName="id")
        **/
        public $mixedEntity;
    }

加载不起作用

$em = $this->getDoctrine()->getManager();
$loadedValue = $em->getRepository('BundleName:EntityContainingInheritedEntity')->findAll();

然而保存

public function indexAction(Request $request)
{
    $floatE = new floatEntity();
    $floatE->floatValue = 1.01;
    $floatE->setId(rand());

    $floatEContainer = new EntityContainingInheritedEntity();
    $floatEContainer->stringValue = 'hello';
    $floatEContainer->mixedEntity = $floatE;

    $intE = new intEntity();
    $intE->intValue = 100;
    $intE->setId(rand());

    $intEContainer = new EntityContainingInheritedEntity();
    $intEContainer->stringValue = 'hello';
    $intEContainer->mixedEntity = $intE;

    $em = $this->getDoctrine()->getManager();
    $em->persist($floatEContainer);
    $em->persist($intEContainer );
    $em->flush();
}

加载时说代理不存在。所以我搜索了一下,首先,当有像这样的继承映射时,学说甚至不应该尝试创建代理(至少我是如何解释文档http://docs.doctrine-project.org/en/2.0.x/reference/inheritance-mapping.html#performance-impact

我已经清除了我的缓存没有改变 我试图在注释中添加急切的加载,没有任何改变 我也有点从我的搜索得到我要使用DQL而不是findAll()下面有相同的代理缓存错误消息

$query = $em->createQuery("SELECT u FROM Path\To\Entity\EntityContainingInheritedEntity u");
$users = $query->getResult();

提到的错误消息:ContextErrorException:警告:require(/path/app/cache/dev/doctrine/orm/Proxies/__CG__BundleNameEntityBaseEntity.php):无法打开流:/ path / vendor / doctrine中没有此类文件或目录/common/lib/Doctrine/Common/Proxy/AbstractProxyFactory.php

顺便说一句,这并没有解决我的问题:Doctrine 2 Inheritance Mapping with Association

1 个答案:

答案 0 :(得分:0)

根据Alberto Fernandez的评论,我不应该做我做的事情。这让我很困惑,因为它保存得当。尽管如此,如果他没有任何关于如何做到这一点的例子,我继续搜索。我发现我的问题的最佳解决方案是不映射关联的实体。相反,我迷上了事件监听器,即 http://symfony.com/doc/current/cookbook/doctrine/event_listeners_subscribers.htmlhttp://docs.doctrine-project.org/projects/doctrine-orm/en/latest/reference/events.html这使我能够坚持并按照我​​想要的方式加载相关实体。我将使用我的解决方案再次使用上面的示例。

EntityContainingInheritedEntity已更改为

/**
* @ORM\Table(name="Entity_Containing_Inherited_Entity")
* @ORM\Entity
* })
*/
class EntityContainingInheritedEntity
{
    /**
     * @ORM\Column(name="id", type="integer")
     * @ORM\Id
     * @ORM\GeneratedValue(strategy="IDENTITY") 
     */
    public $id;

    /**
     * @ORM\Column(name="string_value", type="string")  
     */
    public $stringValue;

    public $mixedEntity;

    public $mixedEntityType;

    public function load($em)
    {
        $this->mixedEntity= $em->getRepository("BundleName:{$this->mixedEntityType}")->find($this->id);
    }

    public function save($em)
    {
        $this->mixedEntity->SetId($this->id);
        $em->persist($this->mixedEntity);
        $em->flush();
    }

    public function delete($em)
    {       
        $em->remove($this->mixedEntity);
        $em->flush();
    }

}

我将此添加到我的config.yml

services:
    my.listener:
        class: Path\To\EventListeners\RecordAssociationManager
        tags:
            - { name: doctrine.event_listener, event: postPersist }
    my.listener2:
        class: Path\To\EventListeners\RecordAssociationManager
        tags:
            - { name: doctrine.event_listener, event: preRemove }
    my.listener3:
        class: Path\To\EventListeners\RecordAssociationManager
        tags:
            - { name: doctrine.event_listener, event: postLoad }

然后制作了事件监听器类

namespace Path\To\EventListeners;

use Doctrine\ORM\Event\LifecycleEventArgs;
use Path\To\Entity\EntityContainingInheritedEntity;

class RecordAssociationManager
{
    public function preRemove(LifecycleEventArgs $args)
    {
        $entity = $args->getEntity();
        $entityManager = $args->getEntityManager();

        if ($entity instanceof EntityContainingInheritedEntity) 
        {
            $entity->delete($entityManager);
        }
    }
    public function postPersist(LifecycleEventArgs $args)
    {
        $entity = $args->getEntity();
        $entityManager = $args->getEntityManager();

        if ($entity instanceof EntityContainingInheritedEntity) 
        {
            $entity->save($entityManager);
        }
    }
    public function postLoad(LifecycleEventArgs $args)
    {
        $entity = $args->getEntity();
        $entityManager = $args->getEntityManager();

        if ($entity instanceof EntityContainingInheritedEntity) 
        {
            $entity->load($entityManager);
        }
    }
}
相关问题