Created
March 30, 2015 13:22
-
-
Save broiniac/17a4338e577ccbe9e090 to your computer and use it in GitHub Desktop.
Doctrine - example search miniengine - Polish comments
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
/** | |
* Filter application via given parameters. | |
* | |
* @param QueryBuilder $qb | |
* @param array $data | |
* | |
* @return QueryBuilder $qb filtered results | |
*/ | |
public function filter($qb, $data = []) { | |
$qb->leftJoin('a.experiences', 'ae') // dołączam referencje (relacje), po których też będę szukał | |
->leftJoin('ae.job', 'j') | |
->leftJoin('a.languages', 'al') | |
; | |
// empty() sprawdza, czy coś niesie ze sobą jakąś wartość | |
// jeżeli coś takiego jak $data['nazwa pola'] | |
// 1. nie istnieje (pole w wyszukiwarce zostało niewypełnione) | |
// 2. przyszło puste (w przypadku niektórych pól przychodzi pusty ciąg znaków) | |
//#notice poniżej "zaawansowany" QueryBuilder (korzystanie z wyrażeń pomocniczych expr) | |
// tutaj szukamy w danych personalnych | |
if (!empty($data['text'])) { | |
$qb->andWhere( //i gdzie | |
$qb->expr()->orX( //pasujące jest którekolwiek z poniższych wyrażeń | |
$qb->expr()->like( //w polu firstname występuje podany ciąg znaków | |
'a.firstname', | |
$qb->expr()->literal('%'.$data['text'].'%') | |
), | |
$qb->expr()->like( //LUB w polu lastname występuje podany ciąg znaków | |
'a.lastname', | |
$qb->expr()->literal('%'.$data['text'].'%') | |
), | |
$qb->expr()->like( //LUB itd... | |
'a.email', | |
$qb->expr()->literal('%'.$data['text'].'%') | |
), | |
$qb->expr()->like( | |
'a.phone', | |
$qb->expr()->literal('%'.$data['text'].'%') | |
), | |
$qb->expr()->like( | |
'a.hobby', | |
$qb->expr()->literal('%'.$data['text'].'%') | |
), | |
$qb->expr()->like( | |
'a.additional', | |
$qb->expr()->literal('%'.$data['text'].'%') | |
) | |
) | |
); | |
} | |
//to samo co powyżej, ale dla danych adresowych | |
if (!empty($data['address'])) { | |
$qb->andWhere( | |
$qb->expr()->orX( | |
$qb->expr()->like( | |
'a.street', | |
$qb->expr()->literal('%'.$data['address'].'%') | |
), | |
$qb->expr()->like( | |
'a.number', | |
$qb->expr()->literal('%'.$data['address'].'%') | |
), | |
$qb->expr()->like( | |
'a.city', | |
$qb->expr()->literal('%'.$data['address'].'%') | |
), | |
$qb->expr()->like( | |
'a.zipCode', | |
$qb->expr()->literal('%'.$data['address'].'%') | |
), | |
$qb->expr()->like( | |
'a.zipCity', | |
$qb->expr()->literal('%'.$data['address'].'%') | |
), | |
$qb->expr()->like( | |
'a.country', | |
$qb->expr()->literal('%'.$data['address'].'%') | |
) | |
) | |
); | |
} | |
// przykład szukania w referencjach (prymitywny) | |
// w polu formularza 'jobs' można było wybrać wiele 'zawodów' | |
// Do akcji indexującej przychodziła wtedy tablica: | |
// [ | |
// 0 => 'pierwsze id', | |
// 1 => 'drugie id', | |
// n => 'n-te id' | |
// ], | |
// gdzie id-ki są oczywiście liczbami całkowitymi. | |
// Poniżej przykład jak obsłużyłem wyszukiwanie | |
if (!empty($data['jobs'])) { | |
$qb->andWhere( | |
// korzystam z expr->in(), który sprawdza, | |
// czy lewy argument znajduje się w tablicy (prawy argument) | |
$qb->expr()->in('j.id', $data['jobs']) | |
); | |
} | |
//tutaj przykład wyszukiwania po wieku (przychodzi liczba całkowita) | |
if (!empty($data['age_min'])) { | |
// do $ageMin wsadzam rok, w który "trafia" dany wiek. Czyli obecny czas minus wiek, który przyszedł | |
$ageMin = new \DateTime("-" . $data['age_min'] . "years"); | |
$qb->andWhere( | |
//lte - lesser then equal - mniejsze lub równe (nie wiem kto to wymyślał) | |
// HERE BE DRAGONS: | |
// baza danych potrafi sprawdzać, który ciąg znaków jest większy. | |
// porównuję więc dwa ciągi znaków - data w bazie z moją datą | |
// Nie lubię takich zabiegów. IMHO są "brudne". Ale skuteczne. | |
$qb->expr()->lte( | |
'a.birthday', //pole, które sprawdzam | |
$qb->expr()->literal( //W bazie siedzi data jako string, np "1991-01-22" | |
$ageMin->format('Y-m-d') //formatuję więc mój wyliczony rok do tego formatu. Resztą zajmuje się expr()->lte() | |
) | |
) | |
); | |
} | |
//to co wyżej, ale "górny przedział" | |
if (!empty($data['age_max'])) { | |
$ageMax = new \DateTime("-" . $data['age_max'] . "years"); | |
$qb->andWhere( | |
$qb->expr()->gte( | |
'a.birthday', | |
$qb->expr()->literal( | |
$ageMax->format('Y-m-d') | |
) | |
) | |
); | |
} | |
// tutaj natomiast porównuję już dwie daty, więc nie muszę niczego wyliczać | |
if (!empty($data['birthday_min'])) { | |
$qb->andWhere( | |
$qb->expr()->gte( // gte - greater then equal - większe lub równe | |
'a.birthday', | |
//trochę "chojraczenie", ale mam pewność, że to co przychodzi ma odpowiedni format (walidacja mi to zapewnia), | |
// więc odważam się wrzucić to bezpośrednio do bazy danych | |
$qb->expr()->literal($data['birthday_min']) | |
) | |
); | |
} | |
if (!empty($data['birthday_max'])) { | |
$qb->andWhere( | |
$qb->expr()->lte( | |
'a.birthday', | |
$qb->expr()->literal($data['birthday_max']) | |
) | |
); | |
} | |
if (!empty($data['price_min'])) { | |
$qb->andWhere( | |
$qb->expr()->gte( | |
'a.price', | |
$data['price_min'] | |
) | |
); | |
} | |
if (!empty($data['price_max'])) { | |
$qb->andWhere( | |
$qb->expr()->lte( | |
'a.price', | |
$data['price_max'] | |
) | |
); | |
} | |
if (!empty($data['readyAt_min'])) { | |
$qb->andWhere( | |
$qb->expr()->gte( | |
'a.readyAt', | |
$qb->expr()->literal($data['readyAt_min']) | |
) | |
); | |
} | |
if (!empty($data['readyAt_max'])) { | |
$qb->andWhere( | |
$qb->expr()->lte( | |
'a.readyAt', | |
$qb->expr()->literal($data['readyAt_max']) | |
) | |
); | |
} | |
// Tutaj 'brudny' sposób - ale szybki i skuteczny | |
// jeżeli coś przyszło i nie jest to równe 0 (istotny warunek)... | |
if (!empty($data['work_type']) && $data['work_type'] != 0) { | |
// to jeżeli to 1, to szukaj tylko w encjach, gdzie pole seasonalWork posiada wartość true | |
// a pole fullWork ma false | |
if ($data['work_type'] == 1) { | |
$qb->andWhere('a.seasonalWork = :true') | |
->andWhere('a.fullWork = :false') | |
; | |
// jeżeli natomiast przyszło 2, to... | |
} else if ($data['work_type'] == 2) { | |
$qb->andWhere('a.seasonalWork = :false') | |
->andWhere('a.fullWork = :true') | |
; | |
} | |
// dlaczego tutaj? bo zawsze jeśli wejdzie do środka tego ifa, to | |
// będę potrzebował zmiennych :true i :false | |
$qb->setParameter('true', 1) | |
->setParameter('false', 0) | |
; | |
} | |
//ok, ale czemu wykluczyłem 0? Bo w formularzu wyświetla mi się coś takiego: | |
// 0 => wszystkie oferty pracy | |
// 1 => TYLKO oferty pracy dorywszej | |
// 2 => TYLKO oferty pracy stałej | |
// w bazie danych siedzi 0 lub 1. Więc to, co przyszło z formularza szukania | |
// wsadzam od razu do QueryBuildera (przez setParameter) | |
if (!empty($data['local'])) { | |
$qb->andWhere('a.local = :local') | |
->setParameter('local', $data['local']) | |
; | |
} | |
if (!empty($data['abroad'])) { | |
$qb->andWhere('a.abroad = :abroad') | |
->setParameter('abroad', $data['abroad']) | |
; | |
} | |
// tutaj nie korzystam z empty(), tylko z | |
// isset oraz != '' | |
// Czemu? Bo tak też można. | |
if (isset($data['status']) && $data['status'] != '') { | |
$qb->andWhere('a.status = :status') | |
->setParameter('status', $data['status']) | |
; | |
} | |
//zrobiłem wszystko - zwracam $qb. | |
// później $qb jest przekazywany do metody paginującej, która sortuje wyniki, | |
// a później wylicza odpowiednią stronę do wyświetlenia (co za tym idzie "kroi" ilość wyników). | |
return $qb; | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment