如何使用具有比较标准的findBy方法


75

我需要使用“ magic finder” findBy方法并使用比较标准(不仅是精确标准)。换句话说,我需要执行以下操作:

$result = $purchases_repository->findBy(array("prize" => ">200"));

这样我就能获得所有奖金在200以上的商品。


6
如果您认为教义或共产主义不是您的事,那么您为项目选择了错误的框架。这些框架对于许多项目确实非常有用。
mask8 8

1
为什么它必须如此神秘?
javier_domenech

Answers:


30

这是一个使用Expr()类的示例-我几天前也需要这样做,花了一些时间来找出确切的语法和用法:

/**
 * fetches Products that are more expansive than the given price
 * 
 * @param int $price
 * @return array
 */
public function findProductsExpensiveThan($price)
{
  $em = $this->getEntityManager();
  $qb = $em->createQueryBuilder();

  $q  = $qb->select(array('p'))
           ->from('YourProductBundle:Product', 'p')
           ->where(
             $qb->expr()->gt('p.price', $price)
           )
           ->orderBy('p.price', 'DESC')
           ->getQuery();

  return $q->getResult();
}

13
如果不是严格需要,请避免使用DQL,这只是使您的逻辑越来越与ORM耦合。
Ocramius

9
@Sliq这是一种教义行为,不一定与symfony有关。
CON

12
@Sliq尝试一些框架之后,你就会意识到,Symfony的不是那么糟糕
玛丽安·齐克Šedaj

如果我看正确,则此函数是存储库方法。在这里,你可以直接进入$this->createQueryBuilder('p'),而不是绕来绕去,通过EntityManager的$this->getEntityManager()->createQueryBuilder()
甘德

201

该类Doctrine\ORM\EntityRepository实现Doctrine\Common\Collections\SelectableAPI。

Selectable界面非常灵活且非常新颖,但是它使您可以轻松地在存储库和单个项目集合上处理比较和更复杂的条件,无论是在ORM还是ODM中还是在完全独立的问题中。

正如您在Doctrine ORM中所要求的那样,这将是一个比较标准2.3.2

$criteria = new \Doctrine\Common\Collections\Criteria();
$criteria->where($criteria->expr()->gt('prize', 200));

$result = $entityRepository->matching($criteria);

该API的主要优点是您可以在此处实现某种策略模式,并且可以与存储库,集合,惰性集合以及SelectableAPI所实现的所有地方一起使用。

这使您可以摆脱为存储库编写的许多特殊方法(如findOneBySomethingWithParticularRule),而专注于编写自己的标准类,每个标准类代表这些特定的过滤器之一。


2
注意:我正在使用带有教义的symfony 2.8.11,并且-也许就在那里-它是“ Criteria :: expr()-> gt()”,而不是“ $ criteria-> expr()-> gt()”。
2016年

3
这是一个静态方法:github.com/doctrine/collections/blob/... 另外:Symfony的是不是教义。具有教义名称和版本的参考教义材料:-P
Ocramius

@Ocramius那么它应该是$criteria::expr()->gt()理想的,不是吗?
AdrianFöder17年

2
Criteria::expr()也可以-随时编辑答案。
Ocramius

1
findOneBySomethingWithParticularRuleIMO拥有像这样的具体存储库方法是一件好事,因为它使您的业务逻辑与Doctrine实现细节(例如标准构建器)脱钩。
戴维

6

您必须使用DQLQueryBuilder。例如,在你的Purchase- EntityRepository你可以做这样的事情:

$q = $this->createQueryBuilder('p')
          ->where('p.prize > :purchasePrize')
          ->setParameter('purchasePrize', 200)
          ->getQuery();

$q->getResult();

对于更复杂的场景,请查看Expr()类


5
避免在并非绝对必要的地方使用DQL。它将您锁定在ORM特定的API中,并且实际上不可重用。在某些情况下需要DQL,但这不是其中一种。
Ocramius

6
如何使用QueryBuilder不能以完全相同的方式将您锁定在学说中?
NDM 2015年



0

我喜欢使用这样的静态方法:

$result = $purchases_repository->matching(
    Criteria::create()->where(
        Criteria::expr()->gt('prize', 200)
    )
);

当然,当条件为1时,您可以推送逻辑,但是当条件更多时,最好将其划分为片段,进行配置并将其传递给方法:

$expr = Criteria::expr();

$criteria = Criteria::create();
$criteria->where($expr->gt('prize', 200));
$criteria->orderBy(['prize' => Criteria::DESC]);

$result = $purchases_repository->matching($criteria);
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.