php - Doctrine 类表继承 - 热切加载子类引用

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

考虑下图:
enter image description here

哪里有User有很多BlogPost的,一个 EventBlogPost 的类型具有 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 {
    ...
}

我现在想构建一个查询来获取给定的用户事件并急切地加载事件 field 。我得到的最接近的是:
$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 的其余部分的属性。

我已经看到我映射的建议 EventsUser :
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'

我应该如何映射类表继承引用?
有没有办法实现我所描述的急切加载?

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

编辑

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

最佳答案

我找到了一种方法来做我想做的事,但我相信一定有更好的方法。

首先编写一个原生查询:

$sql =<<<SQL
SELECT * FROM User user
JOIN BlogPost blog_post ON user.id = blog_post.UserID
JOIN Event event ON blog_post.id = event.BlogPostID
JOIN Venue venue ON event.VenueID = venue.id
WHERE user.id = ?
SQL;

这可以直接通过 $em->getConnection()->prepare() 运行或者最好仍然使用 ResultSetMapping 然后通过 $em->createNativeQuery($sql,$rsm)
$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 来完成,这似乎很遗憾。但据我所知,这是实现这一目标的唯一方法。我很乐意以其他方式展示。

关于php - Doctrine 类表继承 - 热切加载子类引用,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/34614353/

相关文章:

javascript - 如何在php中设置li激活

doctrine-orm - 保留实体而不将其附加到 EntityManager

laravel - eloquent - 获取相关模型特定列的总和

subquery - Sequelize 使用急切加载的模型创建子查询的顶级

php - Fread 内存不足

php - Swiftmailer 仅发送来自 BCC 的 999 封电子邮件

php - 快速实体主义水化器

php - 如何在 Doctrine2 中为类表继承指定外键列?

node.js - 通过中间模型 Sequelize 急切加载

php - Uploadify 不传递变量,Session 问题?