Doctrine类表继承 - 渴望加载子类引用

时间:2016-01-05 14:42:17

标签: php doctrine-orm eager-loading class-table-inheritance

考虑下图: enter image description here

如果UserBlogPostEvent,则BlogPost属于Venue,其属性为** * @ORM\Entity() * @ORM\Table(name="User") */ class User { ... /** * @ORM\OneToMany(targetEntity="BlogPost",mappedBy="User") * @ORM\JoinColumn(...) */ protected $BlogPosts; ... } /** * @ORM\Entity() * @ORM\Table(name="BlogPost") * @ORM\InheritanceType("JOINED") * @ORM\DiscriminatorColumn(...) * @ORM\DiscriminatorMap({...}) * ... */ class BlogPost { ... /** * @ORM\ManyToOne(targetEntity="User",inversedBy="BlogPosts") * @ORM\JoinColumn(...) */ protected $User ... } /** * @ORM\Entity() * @ORM\Table(name="Event") */ class Event extends BlogPost { ... /** * @ORM\ManyToOne(targetEntity="Venue") * @ORM\JoinColumn(...) */ protected $Venue; ... } /** * @ORM\Entity() * @ORM\Table(name="Venue") */ class Venue { ... }

我有以下实体类:

$qb = $em->createQueryBuilder();
$qb
    ->select('User,'BlogPost,Venue')
    ->from('User','User')
    ->join('User.BlogPosts','BlogPost','WITH','BlogPost INSTANCE OF :Event')
    ->join('BlogPost.Venue','Venue')
    ->setParameter('Event',$em->getClassMetadata('Event'));

我现在想要构建一个查询来获取给定的用户事件并急切地加载事件场所。我最接近的是:

Error: Class BlogPost has no association named Venue

这给了我一个相当可预测的错误:

Venue

删除对Event的引用我会让所有用户Event都很好但是我将不得不依赖延迟加载来获取{{1}的其余部分}的属性。

我看到了我在Events中映射User的建议:

class User {
    ...
    /**
     * @ORM\OneToMany(targetEntity="BlogPost",mappedBy="User")
     * @ORM\JoinColumn(name="UserID", referenceColumnName="UserID")
     */
    protected $BlogPosts;

    /**
     * @ORM\OneToMany(targetEntity="Event",mappedBy="User")
     * @ORM\JoinColumn(name="UserID", referenceColumnName="UserID")
     */
    protected $Events;
    ...
}

尝试此操作时,生成的SQL会尝试执行以下操作:

SELECT * FROM User 
JOIN Event ON User.id = Event.user_id
JOIN BlogPost ON BlogPost.id = Event.blog_post_id

其中user_idBlogPost而不是Event的列,因此出现以下错误:

Invalid column name 'user_id'

我应该如何映射Class Table Inherited reference? 有没有办法实现我所描述的急切加载?

我知道我从类,它们的映射和生成的SQL中省略了一些细节。如果某些细节有助于深入了解,请大声说。

修改

这与Single Table Inheritance (STI) with a ManyToOne relationship不同,因为它类表继承而不是单表继承。另外,我对子类的属性的细节感兴趣,想象一下,如果在该示例中,Video有额外的引用。

1 个答案:

答案 0 :(得分:0)

我找到了一种可以做我想要的方式,但我确信必须有更好的方法。

首先编写本机查询:

$em->getConnection()->prepare()

这可以直接通过$em->createNativeQuery($sql,$rsm)运行,也可以更好地使用ResultSetMapping然后通过$rsm = new \Doctrine\ORM\Query\ResultSetMappingBuilder($em); $rsm->addRootEntityFromClassMetadata('User','user'); $rsm->addIndexBy('user','id'); $rsm->addJoinedEntityResult('event','event','user','BlogPosts'); $rsm->addJoinedEntityResult('venue','venue','event','Venue'); $rsm->addFieldResult(); // add all of the fields you are interested in $query = $this->get_manager()->createNativeQuery($sql,$rsm); $query->setParameter(1, $user_id); return $query->getResult($hydration_mode);

运行
QueryBuilder

这似乎无法通过 var uploadDate = new Date(); 完成,但据我所知,这是实现这一目标的唯一方法。我很乐意以其他方式表现出来。