Querybuilder na filtrovanie pomocou AND podmienky
- Br0visT
- Člen | 17
Zdravím, mám problém s Querybuilderom v Doctrine. Potrebujem filtrovať
články podľa zaškrtnutých tagov. Mám tam také zaklikávatko ktoré
rozoznáva filtrovanie medzi AND a OR, teda uvediem príklad.
Mám zaškrtnuté OR filtrovanie. Zaškrtnem tagy: korona, auta, peniaze.
Článok môže mať samozrejme viac tagov. Avšak OR filter vyselektuje všetky
články, ktoré majú aspoň jeden (alebo viacero z týchto tagov).
A teraz by som potreboval AND filtrovanie. Zaškrtnem tagy korona, auta, peniaze a vyselektuje mi len tie články, ktoré obsahujú všetky 3 tagy.
Aby som trošku popísal entity, tak:
Článok je vlastná entita, ktorá ale patrí pod entitu
Produkt (je childom Produktu).
Produkt má id a parent_id, keďže články môžu byť
aktualizované a je treba ukladať každú jednu aktualizáciu.
Na stránke sa zobrazujú vždy iba najnovšie aktualizácie článkov (pre
usera).
Produkt má ManyToMany relation s entitou
Tag.
Keďže OR filtrovanie mi funguje, najprv tu napíšem querybuilder na to:
private function addFilterOr(QueryBuilder $qb, array $tags)
{
return $qb->leftJoin('a.tags', 't')
->leftJoin('a.parent', 'p')
->addSelect('p')
->leftJoin('p.tags', 'pt')
->addSelect('pt')
->andWhere('t IN(:tags) OR pt IN (:tags)')
->setParameter('tags', $tags);
}
Samotne getovanie článkov podľa tohto filtra alebo filtra AND je
nepodstatné, to je vyriešené dobre.
Ak sa vam nieco nezda na tomto filtri, skuste ma opravit, ale momentalne je to
funkcne.
A kedže vo filtri AND potrebujem foreachovať podmienky (kedže tam musí byť kvázi jeden stlpec rovný viacerým hodnotám), tak som to skúsil riešiť takto:
public function addFilterAnd(QueryBuilder $qb, array $tags)
{
$qbAnd = $qb->leftJoin('a.tags', 't')
->leftJoin('a.parent', 'p')
->addSelect('p')
->leftJoin('p.tags', 'pt')
->addSelect('pt')
->andWhere('t IN(:tags) OR pt IN (:tags)')
->setParameter('tags', $tags);
foreach ($tags as $k => $t) {
$qbAnd->andWhere('pt IN(:tagNew'.$k.')')
->setParameter('tagNew'.$k, $t);
}
return $qbAnd;
}
Kvázi tá prvá časť po foreach, je OR filter, takže nájde mi články,
kde je aspoň jeden z tagov. Avšak ja potrebujem aby tam boli všetky
zaškrtnuté, preto ich loopujem pomocou všetkych tagov.
Nebudem moc vysvetľovať, čo to robí, pretože to jednoducho robí
blbosti – filtruje si to kvázi jak chce == jak ja nechcem :D. Neviem čo
robím zle, najlepšie by mi to bolo vysvetliť opravením kódu, keďže na
terminológiu nie som moc frajer :D
Ďakujem za každú pomoc.
- David Matějka
- Moderator | 6445
https://stackoverflow.com/…s-al/3267635#…
do doctrine qb uz to snad prepises :)
- Br0visT
- Člen | 17
David Matějka napsal(a):
https://stackoverflow.com/…s-al/3267635#…
do doctrine qb uz to snad prepises :)
Tak moc nerozumiem, aky je rozdiel oproti mojmu kodu kedze on dava rovno do zatvorky viacero stringov a ja to selektujem dynamicky, teda loopujem prvky arrayu ktore vkladam do andWhere. Radsej by som to teda videl spravne v qb.
- David Matějka
- Moderator | 6445
dulezita je ta cast
GROUP BY o.id
HAVING COUNT(DISTINCT t.name) = 2
jelikoz zadny radek nevyhovuje podmince, ze ma vsechny tagy – dojde totiz dle spojovaci tabulky k roznasobeni radku. ty pak vyfiltrujes ty, ktery splnujou tagy, zgroupujes dle clanku a pres having vyfiltrujes groupy, ktere maji tolik polozek, jako je pocet tagu, ktery potrebujes