2017-12-11 1 views
0

Lassen Sie uns sagen, ich habe 3 Modelle: , Child, GrandChild. Elternteil hasMany() Kind, Kind hasMany() GrandChild. Jetzt, wenn ich das Elternmodell ->delete() bin, bleiben die Kinder- und GrandChild-Modelle unberührt. Aber ich möchte auch die verwandten Modelle löschen. Ich habe versucht, dies zu tun in meinem Kontrolleurs destroy() Methode:Laravel Modell Löschen Hierarchie

$parent->childs->grandchilds()->delete(); 
$parent->childs()->delete(); 
$parent->delete(); 

aber es wirft ein BadMethodCallException, Verfahren grandchilds() nicht existiert, obwohl ich habe eine hasMany() Beziehung Setup auf Child Modell.

Wie kann ich alle verwandten Modelle problemlos löschen, ohne Fremdschlüsseleinschränkungen einrichten zu müssen? Da in meiner Anwendung mehr als 3 verwandte Modelle vorhanden sind, ist die Bearbeitung aller Migrationsdateien zu diesem Zeitpunkt sehr zeitaufwändig.

Antwort

0

Die Art und Weise versucht, funktioniert nicht, weil Sie ->grandchilds()->delete() sind telefonieren auf einer Sammlung von childs, anstatt ein Abfrage-Generator oder ein Modell.

Eine Möglichkeit wäre, über die Kinder foreach:

foreach($parent->childs as $child){ 
    $child->grandchilds()->delete(); // Here you call it on a query builder (relationship) 
    $child->delete(); // Here you call it on a model 
} 
$parent->delete(); // Calling on a model 

Oder Sie könnten eine ->hasManyThrough(Child, GrandChild) Beziehung und löschen so (auch performante einrichten, da Sie nur 3 Anfragen benötigen, unabhängig von der Anzahl der Kinder):

$parent->grandchilds()->delete(); // Assumed the name of hasManyThrough relationship to be "grandchilds" 
$parent->childs()->delete(); 
$parent->delete(); 
+0

Was ist, wenn ich eine Ebene tiefer gehen muss (oder noch mehr zu einem späteren Zeitpunkt), wie kann ich hasManyThrough dann einrichten? Nehmen wir an, ich habe jetzt ein 'GreatGrandChild' Modell, was kann ich dann tun? – Eisenheim

+0

Es gibt keinen schönen Weg, es ohne "on delete cascade" zu machen. Fremdschlüssel sind dort dein bester Freund. Es spart Ihnen auf lange Sicht Zeit und steigert die Leistung. – devk

3

Setup-foreign key constraints with ->onDelete('cascade'), zum Beispiel:

$table->foreign('parent_id')->references('id')->on('parents')->onDelete('cascade'); 

das gleiche in Enkel Migration durchführen.

Wenn Sie in diesem Fall das übergeordnete Modell löschen, sind alle zugehörigen untergeordneten Elemente und Enkelkinder automatically deleted by DB.

+1

Zwar ist dies absolut so, wie es getan werden sollte, sagte Fragesteller speziell> ohne Fremdschlüssel-Constraints – devk

+0

@devk einzurichten, die ich, dass ein Teil verpasst haben. In diesem Fall sollte OP den Code aus Ihrer Antwort unbedingt verwenden. –

0

Wenn Sie aus irgendeinem Grund nicht Kaskadierung umsetzen können, wie durch Alexey vorgeschlagen löscht, können Sie Loops verwenden, um dies zu erreichen:

foreach($parent->childs AS $child){ 
    foreach($child->grandchilds AS $grandchild){ 
    $grandchild->delete(); 
    } 
    $child->delete(); 
} 
$parent->delete();