Je pense que c'est un cas d'utilisation parfait pour les événements Eloquent ( http://laravel.com/docs/eloquent#model-events ). Vous pouvez utiliser l'événement "suppression" pour effectuer le nettoyage:
class User extends Eloquent
{
public function photos()
{
return $this->has_many('Photo');
}
// this is a recommended way to declare event handlers
public static function boot() {
parent::boot();
static::deleting(function($user) { // before delete() method call this
$user->photos()->delete();
// do the rest of the cleanup...
});
}
}
Vous devriez probablement aussi mettre le tout dans une transaction, pour garantir l'intégrité référentielle.
first()
dans la requête pour pouvoir accéder au modèle-événement, par exempleUser::where('id', '=', $id)->first()->delete();
Sourceforeach($user->photos as $photo)
, puis$photo->delete()
pour m'assurer que chaque enfant avait ses enfants supprimés à tous les niveaux, au lieu d'un seul comme cela se passait pour une raison quelconque.Photos
atags
et vous faites la même chose dans lePhotos
modèle (c'est-à-dire sur ladeleting
méthode :),$photo->tags()->delete();
il ne se déclenche jamais. Mais si je fais unefor
boucle et faire quelque chose commefor($user->photos as $photo) { $photo->delete(); }
alors letags
faire aussi supprimé! just FYIVous pouvez en fait configurer cela dans vos migrations:
$table->foreign('user_id')->references('id')->on('users')->onDelete('cascade');
Source: http://laravel.com/docs/5.1/migrations#foreign-key-constraints
la source
Vous pouvez supprimer toutes les photos associées avant de supprimer réellement l'utilisateur.
J'espère que ça aide.
la source
$this->photos()->delete()
. Lephotos()
renvoie l'objet de création de requête.Relation dans le modèle utilisateur:
Supprimer l'enregistrement et associé:
la source
Il existe 3 approches pour résoudre ce problème:
1. Utilisation des événements éloquents sur le modèle de démarrage (réf: https://laravel.com/docs/5.7/eloquent#events )
2. Utilisation des observateurs d'événements éloquents (réf: https://laravel.com/docs/5.7/eloquent#observers )
Dans votre AppServiceProvider, enregistrez l'observateur comme ceci:
Ensuite, ajoutez une classe Observer comme ceci:
3. Utilisation des contraintes de clé étrangère (réf: https://laravel.com/docs/5.7/migrations#foreign-key-constraints )
la source
Depuis Laravel 5.2, la documentation indique que ces types de gestionnaires d'événements doivent être enregistrés dans AppServiceProvider:
Je suppose même de les déplacer vers des classes séparées au lieu de fermetures pour une meilleure structure d'application.
la source
Eloquent::observe()
méthode est également disponible dans la version 5.2 et peut être utilisée à partir de l'AppServiceProvider.photos()
, vous devrez également faire attention - ce processus ne supprimera pas les petits-enfants car vous ne chargez pas de modèles. Vous devrez bouclerphotos
(notez, nonphotos()
) et lancer ladelete()
méthode sur eux en tant que modèles afin de déclencher les événements liés à la suppression.Il vaut mieux remplacer la
delete
méthode pour cela. De cette façon, vous pouvez incorporer des transactions DB dans ladelete
méthode elle-même. Si vous utilisez la voie événementielle, vous devrez couvrir votre appel dedelete
méthode avec une transaction DB à chaque fois que vous l'appelez.Dans votre
User
modèle.la source
Dans mon cas, c'était assez simple car mes tables de base de données sont InnoDB avec des clés étrangères avec Cascade on Delete.
Donc, dans ce cas, si votre table de photos contient une référence de clé étrangère pour l'utilisateur, il vous suffit de supprimer l'hôtel et le nettoyage sera effectué par la base de données, la base de données supprimera tous les enregistrements de photos des données. base.
la source
Je voudrais parcourir la collection en détachant tout avant de supprimer l'objet lui-même.
voici un exemple:
Je sais que ce n'est pas automatique mais c'est très simple.
Une autre approche simple consisterait à fournir au modèle une méthode. Comme ça:
Ensuite, vous pouvez simplement appeler ceci là où vous avez besoin:
la source
Ou vous pouvez le faire si vous le souhaitez, juste une autre option:
Notez que si vous n'utilisez pas la connexion par défaut de laravel db, vous devez effectuer les opérations suivantes:
la source
Pour élaborer sur la réponse sélectionnée, si vos relations ont également des relations enfants qui doivent être supprimées, vous devez d'abord récupérer tous les enregistrements de relations enfants, puis appeler le
delete()
méthode afin que leurs événements de suppression soient également déclenchés correctement.Vous pouvez le faire facilement avec des messages d'ordre supérieur .
Vous pouvez également améliorer les performances en interrogeant uniquement la colonne ID des relations:
la source
oui, mais comme @supersan l'a indiqué en haut dans un commentaire, si vous supprimez () sur un QueryBuilder, l'événement de modèle ne sera pas déclenché, car nous ne chargeons pas le modèle lui-même, puis appelons delete () sur ce modèle.
Les événements sont déclenchés uniquement si nous utilisons la fonction de suppression sur une instance de modèle.
Donc, cet être dit:
afin de supprimer les balises de publication lors de la suppression de l'utilisateur, nous devrons parcourir
$user->posts
et appeler$post->delete()
foreach($user->posts as $post) { $post->delete(); }
-> cela déclenchera l'événement de suppression sur PostCONTRE
$user->posts()->delete()
-> cela ne déclenchera pas l'événement de suppression lors de la publication car nous ne chargeons pas réellement le modèle de publication (nous exécutons uniquement un SQL comme:DELETE * from posts where user_id = $user->id
et donc, le modèle de publication n'est même pas chargé)la source
Vous pouvez utiliser cette méthode comme alternative.
Ce qui va se passer, c'est que nous prenons toutes les tables associées à la table users et supprimons les données associées en utilisant la boucle
la source