2014-12-06 6 views
13

Laravel benutzen, habe ich den folgenden CodeLaravel Eloquent ORM - viele zu viele Delete Pivot-Tabelle Werte links über

$review = Review::find(1); 
$review->delete(); 

Review hat eine viele zu viele Beziehung mit einem Unternehmen Product definiert. Wenn ich eine Überprüfung lösche, würde ich erwarten, dass sie von den zugehörigen Produkten in der Pivot-Tabelle getrennt wird, aber das ist nicht der Fall. Wenn ich den obigen Code ausführe, sehe ich immer noch die Verknüpfungszeile in der Pivot-Tabelle.

Habe ich hier etwas verpasst oder funktioniert Laravel so? Ich bin mir der Methode detach() bewusst, aber ich dachte, dass das Löschen einer Entität sie auch automatisch von allen zugehörigen Entitäten lösen würde.

Review ist wie folgt definiert:

wie diese
<?php 
class Review extends Eloquent 
{ 
    public function products() 
    { 
     return $this->belongsToMany('Product'); 
    } 
} 

Product definiert:

<?php 
class Product extends Eloquent 
{ 
    public function reviews() 
    { 
     return $this->belongsToMany('Review'); 
    } 
} 

Vielen Dank im Voraus.

+0

So funktioniert 'Eloquent'. Sie können DB-Ereignisse für die Pivot-Tabelle verwenden ('on delete cascade') oder Ihre Event-Handler mit Eloquent implementieren. Etwas wie http://StackOverflow.com/a/14174356/784588 –

Antwort

24

Die detach-Methode wird verwendet, um eine Beziehung aus der Pivot-Tabelle zu lösen, während delete den Modelldatensatz selbst löscht, d. H. Den Datensatz in der Übersichtstabelle. Nach meinem Verständnis wird delete implizit nicht gelöscht. Sie können model events verwenden, um eine Bereinigung der Pivot-Tabelle auszulösen, aber etwas mit wie:

Review::deleting(function($review) 
{ 
    $review->product()->detach() 
} 

Auch ich würde vorschlagen, dass die Beziehung eine Eins-zu viele sein würde, als ein Produkt viele Bewertungen haben würde, aber Eine Rezension würde nicht zu vielen Produkten gehören (normalerweise).

class Review extends \Eloquent { 
    public function product() 
    { 
     return $this->belongsTo('Product'); 
    } 
} 

class Product extends \Eloquent { 
    public function reviews() 
    { 
     return $this->hasMany('Review'); 
    } 
} 

Natürlich würde dies erfordern, dass Sie Ihre Datenbankstruktur optimieren. Wenn Sie die Datenbankstruktur und Ihre aktuellen Beziehungen so belassen möchten, wie sie sind, besteht die andere Möglichkeit darin, eine Fremdschlüsseleinschränkung für die Pivot-Tabelle anzuwenden, sodass Sie beim Löschen einer Überprüfung oder eines Produkts die Löschung auf der Basis kaskadieren können Pivot-Tabelle.

// Part of a database migration 
$table->foreign('product_id')->references('id')->on('products')->onDelete('cascade'); 
$table->foreign('review_id')->references('id')->on('reviews')->onDelete('cascade'); 

Edit: die Einschränkung Beim Hinzufügen, drücken Sie die Aufräumarbeiten auf die Datenbank, und müssen sich nicht darum kümmern, es in der Code verarbeitet.

+0

In Ihrem ersten Teil durchlaufen Sie keine Ergebnisse, sondern rufen einfach '$ model-> relation() -> detach()' auf, was alle entfernt Pivot-Verknüpfungen für gegebenes $ -Modell in einer einzelnen Abfrage. –

+0

Vielen Dank. Dies beantwortet meine Frage gründlich. By the way, ich habe eine viele zu viele Beziehung, weil ich eine bestehende Liste von Produktbewertungen habe und einige Leute mehrere Produkte in 1 Stück überprüft haben. –

+0

Wäre toll, 'detach()' -Syntax mit ID des zu lösenden Elements einzuschließen, sowie einen Link zu [detach function] (http://laravel.com/api/5.1/Illuminate/Database/Eloquent/Relations/ BelongsToMany.html # method_detach) oder [example] (http://laravel.com/docs/5.1/eloquent-relationships#inserting-many-to-many-relationships) – QuickDanger

5

Einfachere Schritte:

In diesem Beispiel wird ein Account viele Tags hat:

die Stichworte zu löschen, dann das Konto tun:

// delete the relationships with Tags (Pivot table) first. 
$account->find($this->accountId)->tags()->detach(); 

// delete the record from the account table. 
$account->delete($this->accountId); 

Auf der Pivot-Tabelle stelle sicher, dass du hast -> onDelete ('cascade');

$table->integer('account_id')->unsigned()->index(); 
$table->foreign('account_id')->references('id')->on('accounts')->onDelete('cascade'); 

$table->integer('tag_id')->unsigned()->index(); 
$table->foreign('tag_id')->references('id')->on('tags')->onDelete('cascade'); 
0

$review->product()->sync([]) funktioniert auch.

Allerdings ist $review->product()->detach() viel explizit.