所以我有这个包含文章 (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 代理会立即获取所有这些。
你可以通过两种方式得到你想要的:
- 使用
Reaction
存储库并在那里执行查询,也许加入Courrier
这样您就不必再次查询; 在
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/