Laravel Eloquent Sortuj według relacji kolumna tabeli
Próbowałem sortować produkty z shop_products
tabeli według pinned
kolumny z shop_products_options
tabeli:
$products = Shop\Product::with(['options' => function ($query) {
$query->orderBy('pinned', 'desc');
}])->paginate(5);
Ustawiłem relację w sklepie \ Model Produktu:
public function options()
{
return $this->hasOne('Shop\Options');
}
Ale produkty nie są sortowane. Dostaję zapytanie, które działa tylko z shop_products_options
table.
SELECT * FROM `shop_products_options` WHERE `shop_products_options`.`product_id` in ('8', '9', '10', '11', '12') ORDER BY `pinned` DESC
Jak to naprawić? 2 answers
Eager loading używa osobnych zapytań, więc musisz dołączyć do tego:
$products = Shop\Product::join('shop_products_options as po', 'po.product_id', '=', 'products.id')
->orderBy('po.pinned', 'desc')
->select('products.*') // just to avoid fetching anything from joined table
->with('options') // if you need options data anyway
->paginate(5);
SELECT
klauzula służy do nie dodawania połączonych kolumn do modelu Product
.
Edit: zgodnie z komentarzem @alexw - nadal możesz dołączać kolumny z połączonych tabel, jeśli ich potrzebujesz. Można je dodać do select
lub wywołać addSelect/selectRaw
itp.
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2016-06-20 03:43:32
Nie można sortować według powiązanej kolumny tabeli bez ręcznego łączenia powiązanej tabeli. Jarek odpowiedź jest poprawna ale to może być naprawdę niezręczne:
1.Pierwszy problem polega na tym, że musisz się martwić o select.
->select('products.*')
Powód: bez select() id z shop_products_options można wybrać i uwodnić do modelu produktu.
2.Drugi problem polega na tym, że musisz martwić się o groupBy.
->groupBy('products .id');
Powód: jeśli relacja jest HasOne i istnieje więcej niż jeden shop_products_options dla produktu, zapytanie zwróci więcej wierszy dla produktów.
3.Trzeci problem polega na tym, że musisz zmienić wszystkie inne klauzule where z:
->where('date', $date)
Do
->where('products .date', $date)
Powód: products i shop_products_options mogą mieć atrybut "date" i w takim przypadku bez wybrania atrybutu z tabelą "niejednoznaczna kolumna" zostanie wyrzucony błąd.
4.Czwarty problem polega na tym, że używasz nazw tabel (nie modeli) i to jest również złe i niezręcznie.
->where('products.date', $date)
5.Piąty problem polega na tym, że musisz martwić się o miękkie usuwanie połączonych tabel. Jeśli shop_products_options używa cechy SoftDeletes, musisz dodać:
->where('shop_products_options .deleted_at', '=', null)
Wszystkie powyższe problemy są bardzo frustrujące, a łączenie tabel z eloquent może wprowadzić do kodu wiele problemów. Stworzyłem pakiet, który zajmie się wszystkimi powyższymi problemami i możesz sortować według atrybutu relacji w elegancki sposób, w Twoim przypadku byłoby to: {]}
$products = Shop\Product::orderByJoin('options.pinned', 'desc')->paginate(5);
Aby uzyskać więcej informacji zobacz https://github.com/fico7489/laravel-eloquent-join
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2017-12-17 19:08:34