Eloquent pod pokličkou: whereHas()
Podobně jako metoda has()
, metoda whereHas()
nám umožňuje získat data z databáze, kde se daný vztah shoduje s danými podmínkami. Metoda whereHas()
je však víceméně pohodlnější, jelikož ve skutečnosti deleguje metodu has()
. Její přidanou hodnotou je vytvářet náš kód více explicitní a lépe čitelný. Metoda má také zpřeházené parametry v signatuře, takže hodnoty vkládáme v pohodlnějším pořadí.
Mějme jednoduchý příklad:
Kód pak může vypadat například takto:
$usersWithOverdueTasks = $users->filter(function ($user) {
foreach ($user->tasks as $task) {
if ($task->due_at <= Carbon::now()) {
return true;
}
}
return false;
});
Ačkoliv kód bude fungovat, není moc čitelný a také znamená, že budeme muset načíst všechny uživatele a jejich úkoly do paměti nezávisle na tom, jestli je budeme vůbec při dalším zpracování potřebovat nebo ne. Co kdybychom ale přesunuli tuto logiku na databázovou úroveň?
V následující příkladu můžeme vidět metodu whereHas()
v akci, kdy se databázový dotaz upraví tak, že vybíráme pouze uživatele se zpožděnými úkoly.
User::whereHas('tasks', function ($query) {
$query->where('due_at', '<=', Carbon::now());
})->get();
Za zmínku také stojí, že closure v druhém parametru vkládá instanci Eloquent query builderu, takže máme plný přístup ke všem Eloquent metodám, včetně k jakýmkoliv vlastním metodám, které jsme si definovali v modelu relace, v našem případě tedy v modelu Task
.
Všimněte si, že do poddotazu, který kontroluje existenci našeho vztahu, přibyla navíc klauzule WHERE
. To pak znamená, že úkol bude správně vyhodnocen jen v případě, že jeho termín již uplynul. Tím pádem získáme pouze uživatele, jejichž úkoly jsou po termínu.
public function doesntHave($relation, $boolean = 'and', Closure $callback = null)
{
return $this->has($relation, '<', 1, $boolean, $callback);
}
public function whereDoesntHave($relation, Closure $callback = null)
{
return $this->doesntHave($relation, 'and', $callback);
}