2013-02-09 15 views
53

Musiałbym użyć metody "finder magii" findBy za pomocą kryteriów porównawczych (nie tylko dokładne kryteria). Innymi słowy, muszę zrobić coś takiego:Jak korzystać z metody findBy z kryteriami porównawczymi

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

tak że ja dostać wszystkie zakupy, gdzie nagrodą jest powyżej 200.

+0

Brzydka prawda jest taka: To nie jest możliwe w Symfony, chyba że można zbudować zupełnie duże, nieczytelny, i nieintuicyjne zapytanie o niskim poziomie. I pamiętaj, to jest po prostu bardzo podstawowa rzecz, wyobraź sobie, jak masz do czynienia z bardziej złożonymi pytaniami !. ** Mogę tylko polecić wszystkim NIE używać Symfony! ** – Sliq

+7

@ Sliq dlaczego Symfony tutaj? pochodzi z pakietu Doctrine \ ORM .... Mogę tylko polecić wszystkim, aby zrozumieli coś przed mówieniem ^^ –

+2

Jeśli uważasz, że doktryna lub symfony nie są twoimi rzeczami, wybrałeś niewłaściwe ramy dla swojego projektu. Ramy te doskonale sprawdzają się w przypadku wielu projektów. – mask8

Odpowiedz

26

To jest przykład przy użyciu Expr() Class - Musiałem to też kilka dni temu i zajęło mi trochę czasu, aby dowiedzieć się, jaka jest dokładna składnia i sposób użycia:

/** 
* 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(); 
} 
+9

Unikaj używania DQL, jeśli nie jest to bezwzględnie potrzebne, po prostu sprawiasz, że twoja logika jest coraz bardziej powiązana z ORM. – Ocramius

+2

@Ocramius Po prostu nie da się uniknąć DQL, ponieważ symfony jest tak bzdury, że coś takiego jak -> findBy (X) -> where (Y> 7) jest po prostu niemożliwe:/ – Sliq

+7

@Sliq to zachowanie doktryny i nie koniecznie mieć coś wspólnego z symfony. – con

6

Musisz użyć DQL lub QueryBuilder. Na przykład. w Purchase- EntityRepository mógłby zrobić coś takiego:

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

$q->getResult(); 

Dla jeszcze bardziej skomplikowane scenariusze spojrzeć na Expr() class.

+5

Unikaj używania DQL, jeśli nie jest to absolutnie konieczne. Blokuje użytkownika w interfejsie API ORM i nie nadaje się do ponownego użycia. W niektórych przypadkach wymagany jest DQL, ale nie jest to jeden z nich. – Ocramius

+1

w jaki sposób korzystanie z QueryBuilder nie blokuje cię w doktrynie w dokładnie taki sam sposób? – NDM

143

Klasa Doctrine\ORM\EntityRepository realizuje Doctrine\Common\Collections\Selectable API.

Interfejs jest bardzo elastyczny i całkiem nowy, ale pozwoli na łatwe porównanie porównań i bardziej złożonych kryteriów zarówno w repozytoriach, jak i pojedynczych kolekcjach, niezależnie od tego, czy w ORM lub ODM, czy w całkowicie oddzielnych problemach.

byłoby to kryteria porównania, jak właśnie o jak w Doctrine ORM 2.3.2:

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

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

Główną zaletą tego rozwiązania jest to, że realizują jakiś wzór strategii tutaj i działa z repozytoriów , kolekcje, leniwe kolekcje i wszędzie wdrażany jest interfejs API Selectable.

Pozwala to pozbyć się kilkudziesięciu specjalnych metod napisanych dla repozytoriów (takich jak findOneBySomethingWithParticularRule), a zamiast tego skupić się na pisaniu własnych klas kryteriów, z których każdy reprezentuje jeden z tych konkretnych filtrów.

+1

bardzo ładne podejście! Nie wiedziałem o tej funkcji. Zgadzam się, że to naprawdę oszczędza czas, gdy tworzysz własne kryteria klasy i dopasowujesz je w locie. Ale kiedy próbuję twojego przykładu, rzeczywiste wyrażenie nie jest przekazywane do kryteriów , musisz to zrobić: $ criteria = new Criteria(); $ kryteria-> where ($ criteria-> expr() -> gt ("price", 200)); $ result = $ entityRepository-> matching ($ criteria); – con

+0

Zaktualizowany, przepraszam za pomyłkę :) – Ocramius

+3

bardzo ładne podejście. Thanx Ocramius! – kieste

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); 
Powiązane problemy