web-dev-qa-db-fra.com

Laravel Eloquent ORM - Plusieurs à plusieurs Supprimez les valeurs du tableau croisé dynamique

En utilisant Laravel, j'ai le code suivant

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

Review a une relation plusieurs à plusieurs définie avec une entité Product. Lorsque je supprime un commentaire, je suppose qu'il sera détaché des produits associés dans le tableau croisé dynamique, mais ce n'est pas le cas. Lorsque je lance le code ci-dessus, je vois toujours la ligne de liaison dans le tableau croisé dynamique.

Ai-je oublié quelque chose ou est-ce ainsi que Laravel fonctionne? Je connais la méthode detach(), mais j’ai pensé que la suppression d’une entité la détacherait aussi automatiquement de toute entité associée.

Review est défini comme ceci:

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

Product est défini comme ceci:

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

Merci d'avance.

17
Grant J

La méthode detach est utilisée pour libérer une relation du tableau croisé dynamique, tandis que la suppression supprime l’enregistrement de modèle lui-même, c’est-à-dire celui du tableau de révisions. Je crois comprendre que la suppression ne déclenchera pas le détachement implicitement. Vous pouvez utiliser model events pour déclencher un nettoyage du tableau croisé dynamique, en utilisant quelque chose comme:

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

En outre, je suggérerais que la relation serait une à plusieurs, puisqu'un produit aurait de nombreuses critiques, mais qu'une critique n'appartiendrait pas à beaucoup de produits (généralement).

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

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

Bien entendu, cela nécessiterait alors que vous modifiiez la structure de votre base de données. Si vous souhaitez conserver la structure de la base de données et vos relations actuelles telles quelles, vous pouvez également appliquer une contrainte de clé étrangère sur le tableau croisé dynamique. tableau croisé dynamique.

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

Modifier: en ajoutant la contrainte, vous transmettez le travail de nettoyage à la base de données sans avoir à vous soucier de le gérer dans le code.

38
Michael Dyrynda

Étapes plus simples:

Dans cet exemple, une Account a plusieurs Tags:

Pour supprimer les tags, procédez comme suit:

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

Sur le tableau croisé dynamique, assurez-vous que vous avez -> 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');
8
Mahmoud Zalt

$review->product()->sync([]) fonctionne également.

Cependant, $review->product()->detach() est beaucoup plus explicite.

1
Kazuya Gosho