2016-07-01 16 views
3

Es gibt eine Tabelle namens Anforderungen mit einer Spalte mit dem Namen Status und ich habe Zugriff auf diese Tabelle über eine HasManyThrough Beziehung.Graf Zeilen von jedem Status - Laravel eloquent

Die Tabelle sieht wie folgt aus:

id | status | request 
-------------------------- 
1 | 1 | lorem ipsum 
2 | 2 | lorem ipsum 
3 | 1 | lorem ipsum 
4 | 3 | lorem ipsum 
5 | 1 | lorem ipsum 

Ich brauche alle verschiedenen Statuszeilen auf effiziente Art und Weise zu zählen, ist das Ergebnis ich suche so etwas wie dieses:

status | status_count 
--------------------- 
    1 | 3 
    2 | 1 
    3 | 1 

Auch Ich muss in der Lage sein, etwas in der Art zu tun:

$status[1] Or $status->id[1] // which prints out the count of that status 

Ich kenne diese zwei Optionen, die beide von ihnen re ugly:

1. Die Verwendung von Filtern:

// Through a table named group which contains year column 
$requests = Auth::user()->requests()->where('year', 2016)->get(); 

$status[1] = $requests->filter(
    function($request){ 
     return $request->status == 1; 
})->count(); 

Jetzt habe ich 10 Status-ID, und ich möchte diesen Code 10-mal wiederholen, was ist, wenn ich hatte 100 Status ... so ist es nicht ein gute Wahl.

2. ein Recht SQL erstellen Versuch:
ich weiß die richtige SQL-Anweisung, dies zu tun wie folgt aussieht:

SELECT 'status', COUNT(*) FROM requests GROUP BY status 

Für diese Aussage zu schaffen ich das tue:

$groups = Group::where(['owner_id' => Auth::user()->id, 'year' => 2016]) 
->lists('id'); 

$requests = DB::table('requests') 
    ->select(DB::raw('count(status) as status_count, status')) 
    ->whereIn('group_id', $groups) 
    ->groupBy('status') 
    ->get(); 

Und hier ist mein dd Ausgabe:

array:2 [▼ 
    0 => { 
    +"status_count": "3" 
    +"status": "1" 
    } 
    1 => { 
    +"status_count": "1" 
    +"status": "2" 
    } 
    2 => { 
    +"status_count": "1" 
    +"status": "3" 
    } 
] 

Welche habe ich keine Ahnung, wie kann ich sie verwenden, zum Beispiel wie kann ich wissen, was der Status 2 zählt? Ich kann eine foreach verwenden, um ein Array mit Status als Schlüssel und status_counts als Wert zu erstellen, aber ich suche einen richtigen Weg, dies zu tun.

Eine andere Sache ist, wie kann ich diese SQL-Anweisung durch eloquent und nicht DB erstellen?
Gibt es eine andere Möglichkeit, die ich vermisse?

+0

Ich denke, Sie können es durch Mischen der Funktionen der Sammlung machen. –

Antwort

0

Okay, hier ist das, was ich tat habe:

Zuerst habe ich eine richtige schaffen verwaltet SQL nur mit eloquent und bekommen die Status und ihre Anzahl nur um 1 Anfrage.Hier

ist die hasManyThrough Beziehung:

public function requests() 
{ 
    return $this->hasManyThrough('App\Models\Request', 
        'App\Models\Group', 'owner_id', 'group_id'); 
} 

Dann die Anzahl der gewünschten Anfragen Status zu erhalten:

$requests = Auth::user()->requests()-> 
    select(DB::raw('count(requests.status) as count, requests.status'))-> 
     groupBy('requests.status')->where('year', '2016')->get(); 

Auch unser Ergebnis ist genau so, wie wir wollten:

status | status_count 
--------------------- 
    1 | 3 
    2 | 1 
    3 | 1 

Dieses Mal haben wir zwei Möglichkeiten mit Zählern zu arbeiten, ich gehe zuerst mit dem Neuen:

1. Mit dem:

// returns null if there is no row with status of 1 
$status = $projects->where('status_id', "1")->first(); 
// if $status is null there is no row with status of 1 so return 0 
echo (empty($status)) ? 0 : $status->count; 

einfach nicht wahr? aber es ist nicht so sauber wie wir wollen.

2. Der foreach Trick:

Wie ich es in meiner Frage erwähnte wir eine foreach verwenden können eine Reihe von Zuständen und deren Zählung zu erstellen. Aber was passiert, wenn wir versuchen, die Anzahl eines Status zu ermitteln, der im Ergebnis unserer Abfrage nicht existiert? Wir werden einen Fehler erhalten: Undefinierter Offset.

Und hier ist meine Idee:

Zuerst werden wir ein Array erstellen, um alle Statuscodes zu halten und ihre Zählung dann wir dieses Array mit Null füllen.

Mein System hat nur 10 Statuscode so:

$requests_counts = array_fill(1, 10, 0); // status 1 to 10 - default count: 0 

dann mit einer foreach-Anweisung nur wir die indexs überschreiben, die eine Zählung in unserem Abfrageergebnis haben:

foreach($requests as $request) 
    $requests_counts[$request->status] = $request->count; 

So alle Statuscodes einen Wert zu haben, sogar diejenigen, die nicht in unser Abfrageergebnis existieren.

* Anzahl aller Statuscodes

Aber was, wenn wir wollen, ganz gleich aus der Anzahl aller Anfragen drucken, welche Statuscode haben sie? sollten wir eine andere Abfrage erstellen und alle Ergebniszeilen zählen? Nein, wir verwenden eine Funktion namens array_sum:

array_sum($requests_counts); // prints out number of all requests 
0

Ich würde bei Ihrer zweiten Option mit wenig zwicken bleiben.

$groups = Group::where(['owner_id' => Auth::user()->id, 'year' => 2016]) 
->lists('id'); 

$requests = DB::table('requests') 
    ->select(DB::raw('count(status) as status_count, status')) 
    ->whereIn('group_id', $groups) 
    ->groupBy('status') 
    ->get(); 

$output = []; 
foreach ($requests as $a) 
{ 
    $output[$a->status] = $a->status_count; 
} 

Dann in Ihrem ouput haben Sie $output[1] Zählung für den Status 1 etc ...

+0

Danke, aber wie ich es im letzten Abschnitt meiner Frage erwähnt habe, bin ich mir des foreach Trick bewusst, ich suchte nach etwas besserem. – Ravexina

+0

Sie haben geschrieben 'Was ich nicht weiß, wie kann ich sie benutzen, zum Beispiel, wie kann ich wissen, was der Status 2 zählt '. Und wenn Sie das Array '$ output' füllen, wie im obigen Code, dann verwenden Sie' $ output [1] 'für die Zählung von Status 1,' $ output [2] 'für die Zählung von Status 2 und so weiter ... – KuKeC

+0

Und danach fügte ich folgendes hinzu: Ich kann eine foreach verwenden, um ein Array mit Status als Schlüssel und status_counts als Wert zu erstellen, aber ich suche nach einem richtigen Weg, dies zu tun. ;) Danke nochmal – Ravexina

1
$groups = Group::where(['owner_id' => Auth::user()->id, 'year' => 2016]) 
    ->groupBy('status') 
    ->select(DB::raw('status , COUNT(*) as status_count')) 
    ->get();