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ć?
Author: alexk, 2014-05-08

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.

 64
Author: Jarek Tkaczyk,
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

 8
Author: fico7489,
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