Як використовувати метод findBy за допомогою порівняльних критеріїв


75

Мені потрібно було б використати метод "find magic" findBy за допомогою порівняльних критеріїв (не лише точних критеріїв). Іншими словами, мені потрібно зробити щось подібне:

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

щоб я отримував усі покупки, де виграш перевищує 200.


6
Якщо ви вважаєте, що доктрина чи symfony - це не ваша річ, ви просто вибрали неправильну структуру для свого проекту. Ці рамки чудово працюють для багатьох проектів.
mask8

1
чому це повинно бути настільки загадково
javier_domenech

Відповіді:


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.
Окрамій,

9
@Sliq це доктринна поведінка і не обов'язково має нічого спільного з symfony.
con

12
@Sliq після того, як ви спробуєте ще кілька фреймворків, ви зрозумієте, що Symfony не такий вже і
гадкий

Якщо я добре бачу, ця функція є методом сховища. Тут ви можете перейти прямо до $this->createQueryBuilder('p')замість того , щоб йти навколо, через EntityManager : $this->getEntityManager()->createQueryBuilder().
Гандер,

201

Клас Doctrine\ORM\EntityRepositoryреалізує Doctrine\Common\Collections\SelectableAPI.

SelectableІнтерфейс дуже гнучкий і досить новий, але це дозволить вам обробляти порівняння і більш складні критерії легко на обох сховищ і окремих колекцій предметів, незалежно від того , в ОРЗ або ODM або зовсім різні проблеми.

Це було б критерієм порівняння, як ви щойно просили, як у Doctrine ORM 2.3.2:

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

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

Головною перевагою цього API є те, що ви реалізуєте тут якийсь шаблон стратегії, і він працює зі сховищами, колекціями, ледачими колекціями та скрізь, де Selectableреалізований API.

Це дозволяє вам позбутися десятків спеціальних методів, які ви написали для своїх сховищ (наприклад findOneBySomethingWithParticularRule), і замість цього зосередитись на написанні власних класів критеріїв, кожен із яких представляє один із цих конкретних фільтрів.


2
Примітка: Я використовую symfony 2.8.11 з доктриною і - можливо, просто там - це "Критерії :: expr () -> gt ()", а не "$ критерії-> expr () -> gt ()".
Select0r

3
Це статичний метод: github.com/doctrine/collections/blob/… Також: Symfony - НЕ доктрина. Посилання на доктрини з назвами доктрин та версіями :-P
Окрамій

@ Окраміус, то в ідеалі це повинно бути $criteria::expr()->gt(), ні?
Адріан Федер,

2
Criteria::expr()також добре - сміливо редагуйте відповідь.
Окрамій,

1
Наявність конкретних методів сховища, як findOneBySomethingWithParticularRuleце добре, це IMO, оскільки це відокремлює вашу бізнес-логіку від деталей реалізації Doctrine, таких як критерій побудови.
Девід

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, але це не один із них.
Окрамій

6
як використання QueryBuilder не замикає вас у доктрині точно так само?
NDM



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);
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.