"Si un ouvrier veut bien faire son travail, il doit d'abord affûter ses outils." - Confucius, "Les Entretiens de Confucius. Lu Linggong"
Page de garde > La programmation > Laravel SoftDelete : éviter le problème de contrainte unique

Laravel SoftDelete : éviter le problème de contrainte unique

Publié le 2024-11-06
Parcourir:512

Laravel SoftDelete: Avoiding the Unique Constraint Problem

Cet article provient de https://medium.com/@hafiqiqmal93/laravel-softdelete-avoiding-the-unique-constraint-problem-45381d9745a0

Si vous utilisez Laravel depuis un certain temps, en particulier lorsque les projets impliquent l'intégrité des données, vous avez probablement déjà rencontré la fonctionnalité SoftDelete. Plutôt utile car vous pouvez « supprimer » des enregistrements sans vraiment les retirer de la base de données. Ce que fait Laravel, c'est simplement ajouter un horodatage delete_at afin qu'il le marque comme supprimé, mais reste dans le système. C'est bien beau de conserver des données historiques, mais cela introduit un problème potentiellement délicat : qu'arrive-t-il aux contraintes uniques lorsque vous restaurez des enregistrements supprimés de manière réversible ?


Cela devient un problème lorsque vous souhaitez restaurer un enregistrement qui possède déjà, par exemple, une adresse e-mail ou un nom d'utilisateur unique dans la base de données. Laravel générera simplement une erreur et arrêtera la procédure. Heureusement, il existe un moyen simple d’éviter ce problème de manière très propre.

Examinons une solution utilisant un trait qui vous aidera à contourner les contraintes uniques lors de l'utilisation de SoftDelete dans Laravel.

Comprendre le problème

Prenons un exemple simple. Imaginez que vous ayez une table d'utilisateurs avec un champ email qui doit être unique :


Schema::create('users', function (Blueprint $table) {
    $table->string('email')->unique();
    $table->softDeletes();
});


Si vous supprimez un utilisateur avec l'e-mail [email protected], puis créez ultérieurement un nouvel utilisateur avec le même e-mail, Laravel se plaindra de la contrainte unique sur le champ e-mail, générant une erreur. Dans la même situation, lorsque vous essayez de restaurer l'utilisateur supprimé, Laravel se plaindra également de la contrainte unique sur le champ de courrier électronique et générera la même erreur.

Cela devient un casse-tête, en particulier lorsqu'il s'agit de grands systèmes où la restauration des enregistrements est une tâche courante.

Pour éviter cela, nous pouvons modifier temporairement les valeurs des champs uniques lorsqu'un enregistrement est supprimé de manière logicielle et restaurer les valeurs d'origine lorsque l'enregistrement est ramené. De cette façon, la base de données ne trébuche pas sur la contrainte unique lors des suppressions ou des restaurations logicielles.

La solution : utiliser un trait pour éviter les contraintes en double

Un trait Laravel est un excellent moyen d'encapsuler cette fonctionnalité. Voici une caractéristique que nous pouvons utiliser pour résoudre le problème :


trashed()) {
                foreach ($model->getDuplicateAvoidColumns() as $column) {
                    // handle for Spatie Translatable library
                    if (method_exists($model, 'getTranslatableAttributes')) {
                        $translates = $model->getTranslatableAttributes();
                        if (in_array($column, $translates)) {
                            foreach ($translates as $translate) {
                                if ($translate === $column) {
                                    $values = $model->getTranslations($column);
                                    foreach ($values as $translation => $value) {
                                        $values[$translation] = (explode('--', $value)[1] ?? $value);
                                    }
                                    $model->setTranslations($column, $values);
                                    break;
                                }
                            }
                            continue;
                        }
                    }
                    if ($value = (explode('--', $model->{$column})[1] ?? null)) {
                        $model->{$column} = $value;
                    }
                }
            }
        });
        static::deleted(function ($model): void {
            foreach ($model->getDuplicateAvoidColumns() as $column) {
                // handle for Spatie Translatable library
                if (method_exists($model, 'getTranslatableAttributes')) {
                    $translates = $model->getTranslatableAttributes();
                    if (in_array($column, $translates)) {
                        foreach ($translates as $translate) {
                            if ($translate === $column) {
                                $values = $model->getTranslations($column);
                                foreach ($values as $translation => $value) {
                                    $values[$translation] = time() . '--' . $value;
                                }
                                $model->setTranslations($column, $values);
                                break;
                            }
                        }
                        continue;
                    }
                }
                $model->{$column} = time() . '--' . $model->{$column};
            }
            $model->save();
        });
    }
}


Cette fonctionnalité fait plusieurs choses :

  • Lors de la suppression, il ajoute un horodatage au champ unique, rendant le champ à nouveau unique sans affecter la valeur d'origine. Cette astuce est utile pour maintenir les contraintes uniques satisfaites pendant que l'enregistrement est supprimé de manière logicielle.
  • Lors de la restauration, il supprime l'horodatage, restaurant ainsi la valeur d'origine du champ unique.

Comment ça marche :

  • Gestion des champs uniques : chaque fois qu'un modèle avec ce trait est supprimé, le trait se charge d'ajouter un horodatage aux champs que vous souhaitez garder uniques (exemple : e-mail, nom d'utilisateur). Cela évite les conflits si vous essayez d'ajouter un nouvel enregistrement avec les mêmes valeurs uniques.
  • Gestion des champs traduisibles : Si votre modèle utilise la bibliothèque Spatie Translatable, cette fonctionnalité est suffisamment intelligente pour gérer également les champs multilingues. Il recherche les attributs traduisibles, ajuste leurs valeurs et les enregistre avec l'astuce de l'horodatage.
  • Restauration : Lorsque vous restaurez un enregistrement supprimé de manière réversible, le trait supprime l'horodatage des champs uniques, ramenant le champ à sa valeur d'origine.

Appliquer le trait à votre modèle

Voici comment appliquer ce trait dans votre modèle Laravel :


class User extends Model
{
    use SoftDeletes, AvoidDuplicateConstraintSoftDelete;
    // Specify which columns should avoid the unique constraint issue
    public function getDuplicateAvoidColumns(): array
    {
        return ['email', 'username'];
    }
}


En ajoutant le trait **AvoidDuplicateConstraintSoftDelete** à votre modèle et en spécifiant quelles colonnes doivent éviter les conflits de contraintes uniques (comme e-mail et nom d'utilisateur), vous pouvez facilement éviter ces problèmes. .

Pourquoi cette approche fonctionne-t-elle ?

Cela signifie que, dans le cas d'un enregistrement de suppression logicielle, cela ne provoquerait pas de conflit avec d'autres opérations en raison de certaines contraintes uniques. Ou, en d'autres termes, de cette façon, vous pourrez, en ajoutant l'horodatage aux champs uniques, rendre l'enregistrement « masqué » pour la base de données en termes d'unicité mais toujours récupérable en cas de besoin.

Ceci est très utile lorsque vous avez affaire à une grande base de données et que la restauration des enregistrements est assez courante. Vous n'aurez pas à faire face à chaque fois à l'erreur « entrée en double » chaque fois que vous apportez un utilisateur supprimé de manière logicielle ou tout autre modèle.


Pensées finales

La chose la plus utile dans Laravel est SoftDelete, mais cela donne parfois des maux de tête lorsque l'on travaille avec des contraintes uniques. Voici une solution simple, basée sur des caractéristiques, qui offrira un moyen élégant d'éviter le problème, simplement en modifiant temporairement les champs uniques lors de la suppression et de la restauration ultérieure. De cette façon, vous éviterez des erreurs frustrantes et laisserez votre application fonctionner sans problème sans briser les contraintes uniques de votre base de données.

Si l'un de vos champs a été rendu multilingue ou utilise des bibliothèques comme Spatie's Translatable, la solution ci-dessus fonctionnera sans problème dans chacun de ces cas. Les SoftDeletes sont destinés à vous offrir de la flexibilité et non à vous gêner. Avec le correctif mineur ci-dessus en place, vous éviterez la plupart des pièges et garderez vos données bien rangées et vos utilisateurs satisfaits.


En ajoutant cette fonctionnalité à vos modèles, vous économiserez du temps et des maux de tête, surtout si vous traitez de grands ensembles de données où la suppression logicielle et la restauration sont des opérations fréquentes. Essayez-le dans votre projet Laravel et vous verrez avec quelle fluidité il gère ces problèmes de contraintes uniques délicats !


Merci d'avoir lu ! N'oubliez pas de vous abonner pour rester informé des dernières mises à jour en matière de conception de systèmes et d'innovations en matière de commerce électronique. Bonne conception !

Si vous avez trouvé cet article instructif et que vous souhaitez rester informé avec plus de contenu sur la conception des systèmes et les tendances technologiques, assurez-vous de me suivre sur :-

Twitter : https://twitter.com/hafiqdotcom
LinkedIn : https://www.linkedin.com/in/hafiq93
Achetez-moi du café : https://paypal.me/mhi9388 /
https://buymeacoffee.com/mhitech
Médium : https://medium.com/@hafiqiqmal93

Déclaration de sortie Cet article est reproduit sur : https://dev.to/afiqiqmal/laravel-softdelete-avoiding-the-unique-constraint-problem-8k2?1 En cas de violation, veuillez contacter [email protected] pour le supprimer.
Dernier tutoriel Plus>

Clause de non-responsabilité: Toutes les ressources fournies proviennent en partie d'Internet. En cas de violation de vos droits d'auteur ou d'autres droits et intérêts, veuillez expliquer les raisons détaillées et fournir une preuve du droit d'auteur ou des droits et intérêts, puis l'envoyer à l'adresse e-mail : [email protected]. Nous nous en occuperons pour vous dans les plus brefs délais.

Copyright© 2022 湘ICP备2022001581号-3