假设我有一张桌子,上面有关于节日的信息 每个节日都有开始和结束日期。
我想选择在给定日期生活(发生)的所有节日 这意味着,我想选择他们的开始日期在给定日期之前或之后的所有节日,以及他们的结束日期是在相同的给定日期之后或之后。
所以我继续了节日实体的存储库类,并创建了一种方法来实现这一点 但是标准参数“findBy”期望的是一个数组,所有示例都只将其视为一个简单的标准(例如“array('name'=>'billy')”将选择所有具有billy值的行他们的名字栏,只使用比较运算符。
如何使用其他运算符,例如
>, <, !=, IN, NOT IN, LIKE
等等?
由于
答案 0 :(得分:86)
Doctrine 2.3添加了matching()方法,可让您使用Criteria。
Jeremy Hicks的例子可能是这样写的(注意,这会返回一个ArrayCollection而不是数组)。
public function findActiveFestivals($start, $end)
{
$expr = Criteria::expr();
$criteria = Criteria::create();
$criteria->where($expr->gte('start', $start));
$criteria->andWhere($expr->lte('end', $end);
return $this->matching($criteria);
}
就我个人而言,我不会在这里使用andWhere,并使用更多行来提高可读性,如下所示:
public function findActiveFestivals($start, $end)
{
$expr = Criteria::expr();
$criteria = Criteria::create();
$criteria->where(
$expr->andX(
$expr->gte('start', $start),
$expr->lte('end', $end)
)
);
return $this->matching($criteria);
}
使用IN子句非常简单。
public function findFestivalsByIds($ids)
{
$expr = Criteria::expr();
$criteria = Criteria::create();
$criteria->where($expr->in('id', $ids));
return $this->matching($criteria);
}
Criteria类在Doctrine的非真正ORM或DBAL Common的命名空间中,就像它们的ArrayCollection(它支持的Criteria比EntityRepository更长)。
它的意思是非存储库代码创建sophicated标准的解耦方式。所以在存储库之外使用这个类应该没问题。最近也是QueryBuilder supports Criteria。因此,即使在构建需要QueryBuilder的更复杂的查询时,您也可以使用Criteria为其提供的非数据库代码灵活性。
答案 1 :(得分:21)
如果你想要特定的东西,你需要编写自己的查询(可能使用DQL)。我相信内置的“findBy”方法更适合在没有特定标准的情况下快速抓取对象。我不知道您的实体名称或存储位置。可能是这样的节日存储库中的一个函数。
public function findActiveFestivals($start, $end)
{
$qb = $this->_em->createQueryBuilder();
$qb->select('f')
->from('Festival', 'f')
->where('f.start >= :start')
->andWhere('f.end <= :end')
->setParameters(array('start' => $start, 'end' => $end));
return $qb->getQuery()->getArrayResult();
}
答案 2 :(得分:10)
这不是Doron问题的答案 doctrine有实体存储库,根本不能让我们使用查询...
$this->em->getRepository($this->entity)->findBy(array $criteria);
但他问的是如何在数组$条件中复杂运算符
数组$criteria
的正常格式为array('field'=> $value);
答案 3 :(得分:9)
我一直有同样的问题,由于复杂的查询,我的Doctrine存储库变得非常难看。我还必须将Yii ActiveRecord(带有Criteria对象)转换为Doctrine,而Doctrine当时没有Criteria对象。
我发现blogpost by Benjamin Eberlei根据specification pattern找到了解决此问题的有趣方法。
它使您能够将Query Builder对象的操作推迟到其他类。
$spec = new AndX(
new Equals('ended', 0),
new OrX(
new LowerThan('endDate', new \DateTime()),
new AndX(
new IsNull('endDate'),
new LowerThan('startDate', new \DateTime('-4weeks'))
)
)
);
return $this->em->getRepository('Advertisement')->match($spec)->execute()
此外,您可以组合2个或更多类,这可以创建漂亮的可重用构建块:
public function myQuery(User $user)
{
$spec = new AndX(
new ExpiredAds(),
new AdsByUser($user)
);
return $this->em->getRepository('Advertisement')->match($spec)->execute();
}
在这种情况下,ExpiredAds()和AdsByUser()包含类似于第一个代码示例的结构。
如果您认为该解决方案适合您,请让我建议您可以通过作曲家安装的两个库: