Laravel Eloquent Suma kolumny relacji

111

Pracowałem nad aplikacją Shoppingcart i teraz doszedłem do następującego problemu.

Jest Użytkownik, Produkt i Obiekt Koszyk.
- Tabela Cart zawiera tylko następujące kolumny: „id”, „user_id”, „product_id” i timestamps.
- Model użytkownika „hasMany” Carts (ponieważ użytkownik może przechowywać wiele produktów).
- CartModel „nalezy do” użytkownika i CartModel „hasMany” produktów.

Teraz do obliczenia całkowitej produkty mogę po prostu zadzwonić: Auth::user()->cart()->count().

Moje pytanie brzmi: Jak uzyskać SUMA () cen (kolumna produktu) produktów w koszyku tego Użytkownika?
Chciałbym to osiągnąć za pomocą Eloquent, a nie za pomocą zapytania (głównie dlatego, że uważam, że jest o wiele czystsze).

Admirał
źródło

Odpowiedzi:

220
Auth::user()->products->sum('price');

Dokumentacja jest trochę lekka dla niektórych Collectionmetod, ale wszystkie agregaty konstruktora zapytań są pozornie dostępne poza avg()tymi, które można znaleźć na http://laravel.com/docs/queries#aggregates .

user1669496
źródło
wow dzięki za tę szybką odpowiedź. Teraz mówi tylko, że nie ma kolumny cen. Wygląda na to, że wymownie w ogóle nie patrzy się na tę tabelę produktów ...
theAdmiral
3
Właściwie to ma sens, musisz dodać tabelę produktów do relacji, przepraszam. Wypróbuj $sum = Auth::user()->cart()->products()->sum('price');lub cokolwiek w kolumnie ceny znajduje się w tabeli produktów.
user1669496,
1
To zadziałało dla mnie! Przestałem korzystać z klas wózków. Zarówno użytkownik, jak i produkt mają teraz metodę contribToMany (). Teraz mogę użyć ceny: {{Auth :: user () -> products-> sum ('price')}} Thanx, ten przypadek został rozwiązany.
Admirał
9
Coś tu jest nie tak - twoje łącze odnosi się do stosowania funkcji agregujących do zapytań bazy danych, ale products->sumsugeruje, że jest to suma wywołań na obiekcie kolekcji, a nie na obiekcie konstruktora zwracanym przez products (). Warto wyjaśnić, który z nich masz na myśli, i najlepiej podać link, aby wyjaśnić oba.
Benubird
1
@ user3253002 używając relacji bez nawiasów, ...->products->...wyśle ​​zapytanie do bazy danych, aby pobrać wszystkie produkty powiązane z bieżącym modelem, a następnie będzie pracować z tą kolekcją w pamięci. Użycie ...->products()->...po prostu modyfikuje budowane zapytanie bez wykonywania go, dopóki nie ->sum()zostanie wywołane coś takiego, co może być bardziej wydajne, ponieważ pozwala uniknąć przesyłania niepotrzebnych informacji z bazy danych do pamięci.
Siegen
62

to nie jest twoja odpowiedź, ale dla tych, którzy przyjeżdżają tutaj, szukając rozwiązania innego problemu. Chciałem warunkowo uzyskać sumę kolumny powiązanej tabeli. W mojej bazie danych umowy zawiera wiele działań. Chciałem uzyskać sumę „suma_kwoty” z tabeli Działania, gdzie działania.deal_id = deal.id i działania.status = zapłacone, więc zrobiłem to.

$query->withCount([
'activity AS paid_sum' => function ($query) {
            $query->select(DB::raw("SUM(amount_total) as paidsum"))->where('status', 'paid');
        }
    ]);

wraca

"paid_sum_count" => "320.00"

w atrybucie okazji.

To jest teraz suma, której chciałem nie liczyć.

ahmad ali
źródło
4
W wielu przypadkach jest to najlepsze rozwiązanie, ponieważ można sortować według niego bez konieczności pobierania wszystkich rekordów.
Sabrina Leggett
15

Próbowałem zrobić coś podobnego, co zajęło mi dużo czasu, zanim mogłem rozgryźć funkcję collect (). Więc możesz mieć coś w ten sposób:

collect($items)->sum('amount');

To daje sumę wszystkich pozycji.

Abdur Rahman Turawa
źródło
4
nazwa funkcji to właściwiecollect()
Leonardo Beal
prawdopodobnie lepiej będzie po prostu zapętlić tablicę. collect()służy do wzbogacenia tablicy w obiekt kolekcji, ale jeśli nie masz kolekcji w pierwszej kolejności, może być lepiej użyć po prostu tablicy surowej
Flame
0

Również za pomocą konstruktora zapytań

DB::table("rates")->get()->sum("rate_value")

Aby uzyskać podsumowanie wszystkich wartości stawek wewnątrz stawek tabeli.

Aby uzyskać podsumowanie produktów użytkownika.

DB::table("users")->get()->sum("products")
Ahmed Mahmoud
źródło