2016-09-23 1 views
1

Als Laravel Benutzer seit ein paar Monaten, versuche ich besser zu verstehen, erweiterte Verwendung von Eloquent.Korrekte Art der Handhabung von Oszilloskopen mit Pivot beteiligt

Ich stieß auf einen Fall, in dem ich nicht mit einer Lösung kommen kann, die sich richtig anfühlt.

Ich habe die folgende Struktur bekam (vereinfacht)

Mandate 
id 
status_id 

Mandate_user 
mandat_id 
user_id 
link_status 

User 
id 

Ich erklärte belongsToMany sowohl Benutzer- und Mandat über die Pivot-Tabelle.

auf Benutzer:

public function mandates(){ 
     return belongsToMany(..)->withPivot('link_status'); 
    } 

Ich bin in der Lage akzeptiert Mandate für einen Benutzer zu erhalten, indem

public function acceptedMandates(){ 
    return $this->mandates()->wherePivot('link_status', MandateUserStatus::Accepted); 
} 

mit Das funktioniert aber ich frage mich, ob es wäre ein besserer Weg, durch den Einsatz Bereiche oder andere eloquente Methoden. Und ich versuche akzeptiert Mandate zu erhalten, die auch eine status_id weniger als 4 (die auch aus einer Enum kommt) haben

ich etwas ausgedacht, wie:

public function runningMandates(){ 
    return $this->acceptedMandates()->where('status_id','<', 4); 
} 

Dann sammeln Mandate wie folgt:

$mandates = User::find(1)->runningMandates(); 

Aber würde die eloquente Art und Weise zu tun, so etwas wie:

$mandates = User::find(1)->mandates()->running()->accepted(); 

Danke für Ihre Zeit.

Antwort

2

scopes Fügen Sie der Abfrage Constraints hinzu, so dass Sie die Methode scope verwenden können, um die Abfrage durch Aufrufen von Scope-Methoden zu ändern, die Ihnen schließlich die Chance geben, dynamisch eine Abfrage zu erstellen. Sie können also (wie Sie es getan haben) eine Beziehungsmethode deklarieren, bei der Sie die gesamte Abfrage ausführen und diese spezifische Methode aufrufen oder die Methoden des Bereichs zwei verwenden, um die Abfrage mithilfe von Methodenaufrufen zu erstellen, wobei jede Methode eine Einschränkung hinzufügt. In diesem Fall wird es dynamischer sein, aber es ist immer noch eine Vorliebe und es gibt Ihnen mehr Flexibilität (IMO). Also ja, können Sie Abfrage-Bereiche für das, zum Beispiel verwenden:

// Declare the main relationship 
public function mandates() 
{ 
    return $this->belongsToMany(..)->withPivot('link_status'); 
} 

Nun erklären Abfragebereich für accepted

public function scopeAccepted($query) 
{ 
    return $query->wherePivot('link_status', MandateUserStatus::Accepted); 
} 

Now (eine Einschränkung für die von mandates Methodenaufruf zurückgegeben Abfrage hinzufügen), fügen Sie eine weiteren Abfragebereich für running, zum Beispiel:

public function scopeRunning($query) 
{ 
    return $query->where('status_id','<', 4); 
} 

Nun, wenn Sie etwas likethe folgenden nennen:

Jetzt
$user = User::find(1); 

, rufen Sie die Beziehung Methode (nicht als Eigentum)

$mendates = $user 
->mandates() // The method is called and a query object is constructed 
->running() // Add another constraint into the query: ->where('status_id','<', 4) 
->accepted() // Add another constraint into the query: ... 
->get(); // Finally, execute the query to get the result 

Wahrscheinlich, es ist klar, Sie jetzt. Beachten Sie den Methodenaufruf mandates(), es ist ein Methodenaufruf für die definierte Beziehung, der die Query Builder zurückgibt, und indem Sie weitere Aufrufe der Bereichsmethode verketten, ändern Sie nur die Abfrage, indem Sie weitere Einschränkungen hinzufügen, aber Sie können alle Abfragen in einer Methode ohne dynamische Bereiche ausführen Es liegt also an dir. Während Bereiche gibt Ihnen mehr Flexibilität, aber es bedeutet nicht, dass Sie diesen Ansatz immer folgen müssen, es kommt darauf an.

+0

Danke für das Beispiel. Eine Frage jedoch, wie @Thomas in seiner Antwort darauf hingewiesen hat, würde der akzeptierte Umfang von vorherigem Mandatsantrag abhängen(), oder? sonst ist Pivot Null – Hyti

+0

Ja, genau. Scope arbeitet mit der vorhandenen Abfrage. –

3

Es ist eine sehr subjektive Frage und schwer, eine klare Antwort zu geben, aber hoffentlich kann ich dich davon abhalten, sich selbst zu hinterfragen: Was du machst, ist vollkommen in Ordnung und nicht weniger eloquent als das andere.

Persönlich mag ich, was du machst jetzt viel mehr als das, was du als "eloquenten Weg" präsentierst und schon früher in professionellen Projekten getan hast, aber letztendlich gibt es einen Unterschied in der Art, wie du den Code für ein Framework entwirfst oder Paket, das flexibel sein muss, um viele verschiedene Szenarien zu berücksichtigen, von denen die meisten Sie nicht einmal bei der ersten Version sehen können, im Gegensatz zu dem, wie Sie den Code für eine App entwerfen, die nur von sich selbst verbraucht wird. Wenn Sie die Geschäftslogik kennen, die Ihre App und die Ansichten, die sie ihren Benutzern präsentieren wird (nachfolgend die Abfragen, die sie ausführen muss), anstößt, warum würden Sie keine Methoden erstellen, die das einfach erreichen?

Eloquent beruht auf Verkettung, nicht nur weil es cool ist, sondern weil es nicht weiß (oder wissen möchte), was Ihre Geschäftslogik ist. Für mich ist der "eloquente Weg" mehr über fließenden, lesbaren Code, und ich finde, dass $user->runningMandates besser lesbar ist als $user->mandates()->running()->accepted()->get().

Ich finde auch, dass der erste Ansatz leichter zu bekommen ist. Wenn Sie sich ständig dazu zwingen, Methoden zu trennen, damit sie miteinander verknüpft werden können, ist es schwieriger zu verstehen, welche Methode was macht und welche Methode davon abhängt. Abfragebereiche können die Abfrage nach Belieben ändern (Join, Alias ​​usw.). Die Gefahr besteht also darin, dass eine Methode erfordert, dass eine andere zuerst kommt, da Sie auf einer Tabelle oder Spalte basieren, die nicht in der ursprünglichen Abfrage enthalten ist Eine Methode funktioniert nur in Verbindung mit einer anderen; oder vielleicht versuchen zwei Methoden, der gleichen Tabelle beizutreten oder dieselben Aliase zu verwenden, so dass sie nicht zusammen verwendet werden können.Es mag weit hergeholt scheinen, aber oft wird der Aufwand, die Dinge getrennt und ordentlich zu halten, dazu führen, dass Ihr Code schwerer zu verwenden ist. Aber selbst wenn die Dinge nicht code-weise explodieren, würde der Deal-Breaker für mich die Geschäftslogik vernachlässigen: Ist es in Ihrem Fall sinnvoll, zwei getrennte Bereiche für running und accepted zu haben? Kann ein Mandat running sein, wenn es nicht akzeptiert wird? Wenn nicht, sollten Sie versuchen, zu verhindern, dass ein weniger sachkundiger Entwickler diese fehlerhafte Abfrage (logisch) erstellt. Und wie du schon sagtest, ist die Struktur vereinfacht, so dass es möglicherweise noch weitere Fehler gibt, und viele weitere werden kommen, wenn die App komplexer wird.

Wenn ich den Code von jemand anderem übernehme, würde ich lieber begrenzte, in sich abgeschlossene Methoden haben, die einfache, dezentralisierte Methoden nicht durchbrechen, die erfordern, dass Sie (oft nicht vorhandene) Dokumentation lesen müssen verhindern Sie die vielen Möglichkeiten, sie zu missbrauchen.

+0

Danke! Ich bevorzuge auch meinen Ansatz, aber ich habe mich gefragt, wie die Anwendung immer größer wurde und mein Benutzermodell länger wurde. Ich werde wahrscheinlich je nach Kontext etwas anpassen und verwenden. – Hyti

Verwandte Themen