php - 查询主实体时如何根据特定字段过滤OneToMany关系的实体

标签 php mysql symfony entity relationship

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

express .php

<?php

namespace AppBundle\Entity;

class Courrier
{
    // ...

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

react .php

<?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;

    /**
     * @var integer
     *
     * @ORM\Column(name="status", type="integer")
     */
    private $status;

我的问题是,当我查询 AppBundle:Courrier 存储库时,我想根据 $status 过滤 AppBundle:Reaction。这意味着做类似的事情:

$courrier = $doctrine->getRepository('AppBundle:Courrier')->findOneWithReactionsFiltered($slugCourrier, Reaction::STATUS_ACCEPTED)

所以我构建了这个非常适合存储库的方法,它就在这里:

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 实体及其 Reaction 填充,而不管 $状态

我还转储了 SQL 查询:

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;

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

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                      |
+-------+--------+------------------------------------+ 

有人可以帮忙吗?

最佳答案

这是预期的行为。通过查询 Courrier 存储库,您将获得至少有一个具有您提供的状态的 Reaction 的所有实体。 Reactions 不会立即加入,但是当您访问它的 $reaction ArrayCollection 时,您从存储库获得的 Doctrine 代理会立即获取所有这些。

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

  1. 使用 Reaction 存储库并在那里执行查询,也许加入 Courrier 这样您就不必再次查询;
  2. Courrier 实体中创建一个方法,以根据条件过滤集合结果。可能是这样的:

    public function getReactionsWithStatus($status)
    {
        return $this->reactions->matching(
            Criteria::create()->where(Criteria::expr()->eq('status', $status));
        )->toArray();
    }
    

注意:以下是问题演变后的过时回复

替换参数时,传递时应不带冒号。改变

->setParameter(':courrier', $value)

->setParameter('courrier', $value)

你应该可以开始了。

不要忘记对 react 做同样的事情。

关于php - 查询主实体时如何根据特定字段过滤OneToMany关系的实体,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/37242447/

相关文章:

php - PHP中的登录/注销问题

nginx - 使用 symfony3 提供远程静态文件

mysql - Symfony 2/Doctrine 不在 varchar 字段中保存任何零

php - 带有 express 和 mysql 的 Node.js API - 重新定义获取的参数以进行正确的列搜索

php - 如何使用 curl 正确发送和接收 XML?

php - 在用户部分中对自定义列进行排序在 WordPress 中无法正常工作

php - 尝试用 Javascript 填充字段,由 PHP 回显

MySQL:使用自动增量的整数作为主键 - 我应该将其声明为无符号吗?

symfony - SonataAdminBundle 无法更新用户密码

PHP 表单和 DB 查询输入验证