Как использовать метод findBy со сравнительными критериями

55

Мне нужно будет использовать метод find-метода "волшебный искатель", используя сравнительные критерии (не только точные критерии). Другими словами, мне нужно сделать что-то вроде этого:

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

чтобы получить все покупки, где выигрыш превышает 200.

  • 13
    @Sliq, почему Symfony здесь? это из пакета Doctrine \ ORM .... Я могу только рекомендовать всем разобраться, прежде чем говорить ^^
  • 6
    Если вы думаете, что доктрина или Symfony - это не ваша вещь, вы просто выбрали неверную основу для своего проекта. Эти фреймворки отлично работают для многих проектов.
Показать ещё 1 комментарий
Теги:
doctrine2

5 ответов

25
Лучший ответ

Это пример использования класса 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();
}
  • 11
    Избегайте использования DQL, если в этом нет особой необходимости, это просто делает вашу логику все более и более связанной с ORM.
  • 9
    @Sliq - это доктрина поведения, которая не обязательно имеет отношение к Symfony.
Показать ещё 1 комментарий
141

Класс Doctrine\ORM\EntityRepository реализует Doctrine\Common\Collections\Selectable API.

Интерфейс 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 является то, что вы реализуете какой-то шаблон стратегии здесь, и он работает с репозиториями, коллекциями, ленивыми коллекциями и везде реализуется API Selectable.

Это позволяет вам избавиться от множества специальных методов, которые вы написали для своих репозиториев (например, findOneBySomethingWithParticularRule), и вместо этого сосредоточиться на написании собственных классов критериев, каждый из которых представляет один из этих конкретных фильтров.

  • 4
    очень очень хороший подход. Спасибо Окрамиус!
  • 0
    Хорошая ссылка на шаблоны дизайна!
Показать ещё 6 комментариев
6

Вы должны использовать DQL или QueryBuilder. Например. в вашем Purchase- EntityRepository вы можете сделать что-то вроде этого:

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

$q->getResult();

Для еще более сложных сценариев рассмотрим класс Expr().

  • 5
    Избегайте использования DQL там, где это не является строго необходимым. Он блокирует вас в API, специфичном для ORM, и на самом деле его нельзя использовать повторно. В некоторых случаях требуется DQL, но это не один из них.
  • 2
    Как использование QueryBuilder не блокирует вас в доктрине точно таким же образом?
2

Документация Symfony теперь явно показывает, как это сделать:

$em = $this->getDoctrine()->getManager();
$query = $em->createQuery(
    'SELECT p
    FROM AppBundle:Product p
    WHERE p.price > :price
    ORDER BY p.price ASC'
)->setParameter('price', '19.99');    
$products = $query->getResult();

Из http://symfony.com/doc/2.8/book/doctrine.html#querying-for-objects-with-dql

1
$criteria = new \Doctrine\Common\Collections\Criteria();
    $criteria->where($criteria->expr()->gt('id', 'id'))
        ->setMaxResults(1)
        ->orderBy(array("id" => $criteria::DESC));

$results = $articlesRepo->matching($criteria);

Ещё вопросы

Сообщество Overcoder
Наверх
Меню