首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >在查询主实体时如何基于特定字段过滤OneToMany关系实体

在查询主实体时如何基于特定字段过滤OneToMany关系实体
EN

Stack Overflow用户
提问于 2016-05-15 18:58:38
回答 2查看 47关注 0票数 0

所以我有一个基本的博客,包含文章(AppBundle\Entity\Courrier)和评论(AppBundle\Entity\Reaction)。这两个实体通过OneToMany关系绑定在一起。以下是它们的定义:

Courrier.php

代码语言:javascript
复制
<?php

namespace AppBundle\Entity;

class Courrier
{
    // ...

    /**
     *
     * @ORM\OneToMany(targetEntity="Reaction", mappedBy="courrier")
     */
    private $reactions;

Reaction.php

代码语言:javascript
复制
<?php

namespace AppBundle\Entity;

class Reaction
{
    const STATUS_ACCEPTED = 0;
    const STATUS_PENDING = 1;
    const STATUS_MODERATED = 2;
    const STATUS_TRASHED = 3;

    // ...

    /**
     * Thread of this comment
     *
     * @var Courrier
     * @ORM\ManyToOne(targetEntity="Courrier", inversedBy="reactions")
     * @ORM\JoinColumn(name="courrier_id", referencedColumnName="id")
     */
    private $courrier;

使用

代码语言:javascript
复制
    /**
     * @var integer
     *
     * @ORM\Column(name="status", type="integer")
     */
    private $status;

我的问题是,当我查询AppBundle:Courrier存储库时,我想要过滤基于$statusAppBundle:Reaction。这意味着要做这样的事情:

代码语言:javascript
复制
$courrier = $doctrine->getRepository('AppBundle:Courrier')->findOneWithReactionsFiltered($slugCourrier, Reaction::STATUS_ACCEPTED)

因此,我构建了这个存储库方法,如下所示:

代码语言:javascript
复制
public function findOneWithReactionsFiltered($slug, $status)
{
    return $this->createQueryBuilder('c')
        ->leftJoin('c.reactions', 'r')
        ->where('c.slug = :slug')
        ->andWhere('r.status = :status')
        ->setParameters([
            'slug' => $slug,
            'status' => $status,
        ])
        ->getQuery()
        ->getOneOrNullResult()
    ;
}

但是,此方法的返回值(即$courrier)是用Courrier实体填充的,其Reactions与$status无关。

我还转储了SQL查询:

代码语言:javascript
复制
SELECT c0_.id AS id0, c0_.name AS name1, c0_.slug AS slug2, c0_.envoi AS envoi3, c0_.intro AS intro4, c0_.courrier AS courrier5, c0_.reponse AS reponse6, c0_.published AS published7, c0_.like_count AS like_count8, c0_.recu AS recu9, c0_.image_id AS image_id10, c0_.categorie_id AS categorie_id11 FROM courrier c0_ LEFT JOIN reaction r1_ ON c0_.id = r1_.courrier_id WHERE c0_.slug = 'yaourt-cerise' AND r1_.status = 0;

最后,这里是表的一个小转储:

代码语言:javascript
复制
mysql> select r.id, r.status, c.slug from reaction as r left join courrier as c on c.id = r.courrier_id order by c.slug asc;
+-------+--------+------------------------------------+
| id    | status | slug                               |
+-------+--------+------------------------------------+
| 15533 |      1 | yaourt-cerise                      |
| 15534 |      1 | yaourt-cerise                      |
| 15535 |      1 | yaourt-cerise                      |
| 15536 |      1 | yaourt-cerise                      |
| 15537 |      1 | yaourt-cerise                      |
| 15538 |      1 | yaourt-cerise                      |
| 15539 |      1 | yaourt-cerise                      |
| 15540 |      1 | yaourt-cerise                      |
| 15541 |      1 | yaourt-cerise                      |
| 15526 |      0 | yaourt-cerise                      |
| 15542 |      1 | yaourt-cerise                      |
| 15527 |      1 | yaourt-cerise                      |
| 15543 |      1 | yaourt-cerise                      |
| 15528 |      1 | yaourt-cerise                      |
| 15544 |      1 | yaourt-cerise                      |
| 15529 |      1 | yaourt-cerise                      |
| 15545 |      1 | yaourt-cerise                      |
| 15530 |      1 | yaourt-cerise                      |
| 15546 |      1 | yaourt-cerise                      |
| 15531 |      1 | yaourt-cerise                      |
+-------+--------+------------------------------------+ 

有人能帮忙吗?

EN

回答 2

Stack Overflow用户

回答已采纳

发布于 2016-05-15 19:53:46

您需要选择这两个实体水合物,然后进入集合上的查询。

例如,需要为r别名添加另一个select:

代码语言:javascript
复制
->addSelect('r')

然后,您的集合将正确加载并从查询中筛选。

欲了解更多信息,请参见下面的答案:

Filtering of associated entity collection in Symfony / Doctrine

票数 1
EN

Stack Overflow用户

发布于 2016-05-15 19:07:56

这是故意的行为。通过查询Courrier存储库,您将得到至少有一个具有所提供状态的Reaction的实体。Reactions并没有立即加入,但是您从存储库获得的Doctrine代理一旦访问它的$reaction ArrayCollection就会全部获取它们。

你可以通过两种方式得到你想要的东西:

  1. 使用Reaction存储库并在那里执行查询,可能加入Courrier使您不必再对其进行查询;
  2. Courrier实体中创建一个方法,根据标准筛选集合结果。可能是这样的: 公共函数Criteria::create()->where(Criteria::expr()->eq('status',getReactionsWithStatus($status) {返回$this-> return >matching($status$status);)->toArray();}

注意:以下是这个问题演变为以来的过时回答

在替换参数时,应该在没有冒号的情况下传递它们。变化

代码语言:javascript
复制
->setParameter(':courrier', $value)

代码语言:javascript
复制
->setParameter('courrier', $value)

你应该可以走了。

不要忘记为reaction做同样的事情。

票数 2
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/37242447

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档