Php Doctrine2:获取实体中直接映射的一对多关系的计数

Php Doctrine2:获取实体中直接映射的一对多关系的计数,php,doctrine-orm,symfony,Php,Doctrine Orm,Symfony,我正在使用doctrine2和symfony3.1 我有一个电影列表,人们可以使用一对多关系购买电影票 在仪表板上,我想显示电影列表,以及每部电影的购票数量 我通过这样做得到了我想要的数据 $manager = $this->getDoctrine()->getManager(); $builder = $manager->createQueryBuilder(); $results = $builder ->select('m'

我正在使用doctrine2和symfony3.1

我有一个
电影
列表,人们可以使用一对多关系购买
电影票

在仪表板上,我想显示电影列表,以及每部电影的购票数量

我通过这样做得到了我想要的数据

    $manager = $this->getDoctrine()->getManager();
    $builder = $manager->createQueryBuilder();

    $results = $builder
        ->select('m')
        ->from('AppBundle:Movie', 'm')
        ->addSelect($builder->expr()->count('t'))
        ->leftJoin('m.tickets', 't')
        ->groupBy('m.id')
        ->getQuery()
        ->getResult()
    ;
它可以制作100部电影,1个请求:

SELECT
       e0_.title AS title_0,
       e0_.is_published AS is_published_1,
       e0_.description AS description_2,
       e0_.author AS author_3,
       e0_.director AS director_4,
       e0_.artist_list AS artist_list_5,
       e0_.tags_list AS tags_list_6,
       e0_.creation_time AS creation_time_7,
       e0_.id AS id_8,
       COUNT(t1_.id) AS sclr_9,
       e0_.place_id AS place_id_10,
       e0_.organization_id AS organization_id_11,
       e0_.inner_image1_id AS inner_image1_id_12,
       e0_.inner_image2_id AS inner_image2_id_13,
       e0_.inner_image3_id AS inner_image3_id_14,
       e0_.image_id AS image_id_15
FROM event e0_
LEFT JOIN event_occurence e2_ ON e0_.id = e2_.event_id
LEFT JOIN ticket t1_ ON e2_.id = t1_.occurence_id
WHERE e0_.organization_id = '956744cb-6f76-4328-8ea5-c9715d762509'
GROUP BY e0_.id
LIMIT 100;
就发出的SQL请求而言,这正是我想要的

问题在于ORM方面,结果是这样组织的

[
   [ movie, nbrTickets],
   [ movie, nbrTickets],
   [ movie, nbrTickets],
]
我想知道如何给条令提供提示,以便
nbridockets
直接成为
Movie
的一个属性(目前我必须迭代自己),同时仍然只执行1sql查询(我强烈强调,所以我不想在我的小树枝中执行
Movie.tickets | length

答案应符合以下要求:

  • 执行1且仅执行一个SQL查询(=>否则,当我的页面显示100部电影时,它将仅为此发出101个查询)
  • 允许直接从实体中访问结果(=>否则如上所述,我已经有了一个检索所需数据的解决方案,我对使代码更符合ORM感兴趣)
  • 不要检索太多数据

回答“这在理论上目前是不可能的”也是可以接受的。

您需要适当的注释,以便在电影和票证实体中工作

电影实体:

 * One user has Many tickets.
 * @ORM\OneToMany(targetEntity="Ticket", mappedBy="user")
 */
private $tickets;
票证实体:

 * Many tickets have One movie.
 * @ORM\ManyToOne(targetEntity="movie", inversedBy="tickets")
 * @ORM\JoinColumn(name="movie_id", referencedColumnName="id")
 */
private $movie;
对于关系,需要在构造函数中定义数组集合

public function __construct() {
    $this->tickets = new ArrayCollection();
}
您需要为电影实体创建一个getTickets函数,如下所示:

 * tickets
 *
 * @return arrayCollection
 */
public function getTickets()
{
    return $this->tickets;
}
然后使用以下存储库调用检索电影:

    $movies = $this->getDoctrine()
        ->getRepository('AppBundle:movies')
        ->findAll();
最后,您将检索票证:

    $tickets = $movies[0]->getTickets()
你用以下数字来计算:

    $tickets->count()

目前,似乎没有简单的方法将其直接映射到实体中。您只能执行近似的解决方案:(完成工作,但不那么优雅)

  • 使用
    $movie->tickets->count()
    ,这很优雅,但成本太高(您为每部电影多执行一个sql请求)
  • 使用
    addSelect
    (我当前的解决方案),它会请求获取所有数据,但需要额外的代码来映射实体中的计数

在原则1中似乎有一个解决方案,正如您所解释的那样,您可以访问一个特殊属性
$this->\u values
,该属性包含实体中的非映射值,但似乎不再是这种情况。

使用
{movie.tickets | length}有什么问题吗
在您的小树枝文件中?这似乎是一个简单的解决方案。或者您需要控制器中的计数?因为这样做会触发n+1问题,现在这样做将需要再执行n个SQL请求以显示n个电影。我在这里只看到一个解决方案。将结果添加到数组中。然后您可以传递任何需要的内容。因此
getArrayResult()
应该在这里工作,而不是
getResult()
但是当然你没有对象。或者其他东西。如果你做了类似
->select('m','result')->leftJoin('m.results','result')
的事情,你可以使用
{movie.tickets | length}
并且它应该进行一次db查询。@user254319 hmm很有趣,但这不意味着如果一部电影卖出那么多,ORM会在PHP内存中创建13456个Tickets对象吗?不幸的是,这已经是我拥有的了(我应该对它进行精确计算)。这将发出一个计数请求pert电影,因此如果我显示畅销电影前100名,现在我的页面将发出101查询。我已更新了我的问题,以便更清楚地了解我要查找的内容。