2014-12-06 14 views
13

Utilizzando laravel, ho il seguente codicelaravel Eloquente ORM - molti a molti Elimina Pivot Table Valori rimasto

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

Review ha una relazione molti a molti definito con un'entità Product. Quando elimino una recensione, mi aspetto che venga rimossa dai prodotti associati nella tabella pivot, ma non è questo il caso. Quando eseguo il codice sopra, vedo ancora la riga di collegamento nella tabella pivot.

Ho perso qualcosa qui o è così che funziona Laravel? Sono a conoscenza del metodo detach(), ma ho pensato che l'eliminazione di un'entità lo avrebbe anche separato automaticamente da qualsiasi entità correlata.

Review è definito così:

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

Product è definito così:

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

Grazie in anticipo.

+0

Ecco come funziona 'Eloquent'. È possibile utilizzare gli eventi DB per la tabella pivot ('on delete cascade') o implementare i gestori di eventi utilizzando Eloquent. Qualcosa come http://stackoverflow.com/a/14174356/784588 –

risposta

24

Il metodo di scollegamento viene utilizzato per rilasciare una relazione dalla tabella pivot, mentre delete elimina il record del modello stesso, ovvero il record nella tabella di recensioni. La mia comprensione è che l'eliminazione non innescherà lo scollegarsi implicitamente. È possibile utilizzare model events per innescare una pulizia della tabella pivot, però, utilizzando qualcosa di simile:

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

Inoltre, vorrei suggerire che il rapporto sarebbe stato un uno a molti, come un unico prodotto avrebbe avuto molte recensioni, ma una recensione non apparterrebbe a molti prodotti (di solito).

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

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

Naturalmente, questo richiederebbe di modificare la struttura del database. Se si desidera lasciare la struttura del database e le relazioni correnti come sono, l'altra opzione sarebbe applicare un vincolo di chiave esterna sulla tabella pivot, in modo tale che quando una recensione o un prodotto viene rimosso, è possibile sovrapporre l'eliminazione sul tabella pivot.

// 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: In aggiunta del vincolo, è spingere il lavoro di pulizia al database, e non devono preoccuparsi di gestire nel codice.

+0

Nel primo pezzo non si itera attraverso i risultati, ma semplicemente si chiama '$ model-> relation() -> detach()' cosa rimuoverà tutto associazioni pivot per il dato '$ model' in una singola query. –

+0

Mille grazie. Questo risponde esaurientemente alla mia domanda. A proposito, ho una relazione molte a molte perché ho un elenco esistente di recensioni di prodotti e alcune persone hanno recensito più prodotti in 1 pezzo. –

+0

Sarebbe fantastico includere la sintassi 'detach()' con ID dell'articolo da staccare, così come un collegamento a [detach function] (http://laravel.com/api/5.1/Illuminate/Database/Eloquent/Relations/ BelongsToMany.html # method_detach) o [example] (http://laravel.com/docs/5.1/eloquent-relationships#inserting-many-to-many-relationships) – QuickDanger

5

Passi più semplice:

In questo esempio un Account ha molte Tags:

Per eliminare i tag, quindi l'account fanno questo:

// 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); 

Sulla tabella pivot assicurati di avere -> onDelete ('cascata');

$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([]) funziona anche.

Tuttavia $review->product()->detach() è molto esplicitamente.