2012-01-21 12 views
16

To może wydawać się prymitywną prośbą, ale nie mogę sprawić, żeby zadziałało, więc albo brakuje mi czegoś głupiego, albo nie rozumiem, jak to zrobić. Z góry dziękuję.Doctrine 2.1 DQL - Wiele-do-wielu zapytań wielu wartości - Pozycja w wielu kategoriach?

Mam dwie jednostki doktryny o relacji wielu do wielu: elementy i kategorie. Do których dołączają item_has_categories.

/** 
* Item 
* 
* @Table(name="items") 
* @Entity(repositoryClass="Entity\Repository\Item") 
*/ 
class Item 
{ 

.... 

/** 
* @var Categories 
* 
* @ManyToMany(targetEntity="Categorie", inversedBy="items", cascade={"persist"}) 
* @JoinTable(name="items_has_categories", 
* joinColumns={ 
*  @JoinColumn(name="items_id", referencedColumnName="id") 
* }, 
* inverseJoinColumns={ 
*  @JoinColumn(name="categories_id", referencedColumnName="id") 
* } 
*) 
*/ 
private $categories; 

.... 
} 

/** 
* Categorie 
* 
* @Table(name="categories") 
* @Entity(repositoryClass="Entity\Repository\Categorie") 
*/ 
class Categorie 
{ 
..... 

/** 
* @var Items 
* 
* @ManyToMany(targetEntity="Item", mappedBy="categories") 
*/ 
private $items; 

.... 
} 

A co próbuję zrobić, to uruchomić kwerendę, aby przywrócić wszystkie elementy, które są w każdym z „x” liczby kategorii - co myślę/myśl powinna być SELECT z I i klauzula:

class Item extends EntityRepository 
{ 
    public function findItemsByCategories($categories) 
    { 

    $qString = 'SELECT j, t, c FROM Technique\Entity\Item j LEFT JOIN j.itemImages t JOIN j.categories c WHERE'; 

    $i = 0; 
    foreach ($categories as $c) 
    { 
     $qString .= ' c.name = ?' . $i; 

     if ($i < (count($categories)-1)) 
     { 
      $qString .= ' AND'; 
     } 
     $i++; 
    } 

    $query = $this->_em->createQuery($qString); 
    $query->setParameters($categories); 

    return $query->getResult(); 
} 

że trochę kodu nie ma błędów i wypluwa następujące zapytanie DQL wybrać (po 2 kategorie są wysyłane w tablicy: $ kategorie):

SELECT j, t, c FROM Technique\Entity\Item j LEFT JOIN j.itemImages t JOIN j.categories c WHERE c.name = ?0 AND c.name = ?1 

to zawsze zwraca pustą tablicę tzn. brak wyniku s. Mimo że w moim DB jest więcej niż 20 pozycji spełniających kryteria: są w obu kategoriach.

Ktoś widzi, co robię źle? Czy to ma być selekcja ORAZ ...? Zasadniczo chciałbym wiedzieć, jak zapytać o relację wiele do wielu w Doctrine 2+, gdzie jest więcej niż jedna wartość, która musi zostać spełniona ...

Odpowiedz

40

Dla każdego zainteresowanego, wymyśliłem to (boleśnie). Doctrine powinno to wyjaśnić lepiej zamiast jednej linii, którą mają na stronie DQL ...

Zasadniczo nie jest to zapytanie AND, to CZŁONEK I zapytanie. Dla każdej kategorii członkiem musi być utworzona, a następnie dodaje się do całego zapytania z oraz:

SELECT j, t FROM Entity\Item j LEFT JOIN j.itemImages t WHERE ?0 MEMBER OF j.categories AND ?1 MEMBER OF j.categories AND ?2 MEMBER OF j.categories, etc. 

To zwróci wszystkie elementy, które są we wszystkich kategoriach wnioski.

+1

Dziękujemy za udostępnienie znaleziska. Już miałem zrezygnować z bardzo podobnego problemu, ale CZŁONEK wykonał lewę. Najlepsze dla ciebie. –

+1

Wreszcie przyjemny sposób to zrobić. CZŁONEK naprawdę powinien być bardziej udokumentowany. Nawet nie wiedział, że to istnieje. Wielkie dzięki. – ZolaKt

+1

Z moich eksperymentów metoda ta spowoduje uruchomienie wielu sub-zapytań. Jeśli DQL to zaakceptuje, lepiej będzie, jeśli podasz zapytanie i klauzule WHERE, które używają IN(). Będę eksperymentować i odpowiedzieć, jeśli to nadal działa w DQL. – Lewis

Powiązane problemy