Laravel Eloquent Summe der Spalte der Beziehung


110

Ich habe an einer Shoppingcart-Anwendung gearbeitet und bin jetzt zu folgendem Problem gekommen.

Es gibt einen Benutzer, ein Produkt und ein Warenkorbobjekt.
- Die Cart-Tabelle enthält nur die folgenden Spalten: "id", "user_id", "product_id" und Zeitstempel.
- Das UserModel "hasMany" Carts (da ein Benutzer mehrere Produkte speichern kann).
- Das CartModel "gehört einem Benutzer" und das CartModel "hat viele" Produkte.

Um nun die Gesamtmenge der Produkte zu berechnen, kann ich einfach anrufen : Auth::user()->cart()->count().

Meine Frage ist: Wie kann ich die Summe () der Preise (eine Produktspalte) der Produkte im Warenkorb von diesem Benutzer erhalten?
Ich möchte dies mit Eloquent erreichen und nicht mit einer Abfrage (hauptsächlich, weil ich glaube, dass es viel sauberer ist).

Antworten:


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

Die Dokumentation ist für einige CollectionMethoden ein wenig leicht , aber alle Aggregate für den Abfrage-Generator scheinen verfügbar zu avg()sein. Sie finden sie unter http://laravel.com/docs/queries#aggregates .


wow danke für diese schnelle Antwort. Es heißt jetzt nur, dass es keine Preisspalte gibt. Es sieht so aus, als würde Beredsamkeit diese Produkttabelle überhaupt nicht betrachten ...
TheAdmiral

3
Eigentlich macht das Sinn, Sie müssen die Produkttabelle zur Beziehung hinzufügen, sorry. Versuchen Sie $sum = Auth::user()->cart()->products()->sum('price');oder was auch immer die Preisspalte auf Ihrer Produkttabelle ist.
user1669496

1
Das hat bei mir funktioniert! Ich habe aufgehört, die Wagenklassen zu benutzen. Sowohl der Benutzer als auch das Produkt verfügen jetzt über eine GehorsameToMany () -Methode. Jetzt kann ich price verwenden: {{Auth :: user () -> products-> sum ('price')}} Danke, dieser Fall ist gelöst.
TheAdmiral

9
Hier stimmt etwas nicht ganz - Ihr Link bezieht sich auf das Anwenden von Aggregatfunktionen auf Datenbankabfragen, products->sumimpliziert jedoch , dass es sich um eine Aufrufsumme für ein Auflistungsobjekt handelt und nicht für das von products () zurückgegebene Builder-Objekt. Es lohnt sich zu klären, welche Sie hier meinen, und im Idealfall einen Link bereitzustellen, um beide zu erklären.
Benubird

1
@ user3253002, das eine Beziehung ohne Klammern verwendet, fragt ...->products->...die Datenbank ab, um alle zugehörigen Produkte des aktuellen Modells abzurufen, und arbeitet dann mit dieser In-Memory-Sammlung. Wenn Sie ...->products()->...nur verwenden, wird die Abfrage ->sum()geändert , ohne sie auszuführen, bis so etwas wie aufgerufen wird. Letzteres kann effizienter sein, da unnötige Informationen aus der Datenbank nicht in den Speicher übertragen werden.
Siegen

62

Dies ist nicht Ihre Antwort, sondern für diejenigen, die hierher kommen und nach einer Lösung für ein anderes Problem suchen. Ich wollte die Summe einer Spalte einer verwandten Tabelle bedingt erhalten. In meiner Datenbank hat Deals viele Aktivitäten. Ich wollte die Summe des "Betrags" aus der Tabelle "Aktivitäten" abrufen, in der activity.deal_id = deal.id und activity.status = bezahlt sind, also habe ich dies getan.

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

es kehrt zurück

"paid_sum_count" => "320.00"

im Deals-Attribut.

Dies ist nun die Summe, die ich nicht zählen wollte.


3
Dies ist in vielen Fällen das Beste, da Sie danach sortieren können, ohne alle Datensätze abrufen zu müssen.
Sabrina Leggett

15

Ich habe versucht, etwas Ähnliches zu tun, was mich viel Zeit gekostet hat, bis ich die Funktion collect () herausgefunden habe. So können Sie etwas haben:

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

Dies gibt Ihnen die Gesamtsumme aller Artikel.


4
Der Name der Funktion ist eigentlichcollect()
Leonardo Beal

Sie sind wahrscheinlich besser dran, wenn Sie nur das Array schleifen. collect()wird verwendet, um ein Array in ein Sammlungsobjekt anzureichern. Wenn Sie jedoch überhaupt keine Sammlung haben, ist es möglicherweise besser, nur das Roh-Array zu verwenden
Flame

0

Verwenden Sie auch den Abfrage-Generator

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

Um die Summe aller Tarifwerte innerhalb der Tabellensätze zu erhalten.

Um eine Zusammenfassung der Benutzerprodukte zu erhalten.

DB::table("users")->get()->sum("products")
Durch die Nutzung unserer Website bestätigen Sie, dass Sie unsere Cookie-Richtlinie und Datenschutzrichtlinie gelesen und verstanden haben.
Licensed under cc by-sa 3.0 with attribution required.