Este artículo se originó en https://medium.com/@hafiqiqmal93/laravel-softdelete-avoiding-the-unique-constraint-problem-45381d9745a0
En caso de que hayas estado usando Laravel por un tiempo, especialmente cuando los proyectos involucran integridad de datos, lo más probable es que ya hayas encontrado la función SoftDelete. Bastante útil porque puedes "eliminar" registros sin sacarlos realmente de la base de datos. Lo que hace Laravel es simplemente agregar una marca de tiempo eliminado_at para que lo marque como eliminado, pero permanezca en el sistema. Está muy bien conservar datos históricos, pero introduce un problema potencialmente complicado: ¿qué sucede con las restricciones únicas cuando se restauran registros eliminados temporalmente?
Esto se convierte en un problema cuando desea restaurar un registro que ya tiene, por ejemplo, un correo electrónico o nombre de usuario único en la base de datos. Laravel simplemente arrojará un error y detendrá el proceso. Afortunadamente, existe una manera sencilla de evitar este problema de una manera muy limpia.
Analicemos una solución que utiliza un rasgo que le ayudará a evitar las restricciones únicas al utilizar SoftDelete en Laravel.
Tomemos un ejemplo básico. Imagina que tienes una tabla de usuarios con un campo de correo electrónico que debe ser único:
Schema::create('users', function (Blueprint $table) { $table->string('email')->unique(); $table->softDeletes(); });
Si eliminas temporalmente un usuario con el correo electrónico [email protected] y luego creas un nuevo usuario con el mismo correo electrónico, Laravel se quejará de la restricción única en el campo de correo electrónico, generando un error. En la misma situación, cuando intentas restaurar el usuario eliminado, Laravel también se quejará de la restricción única en el campo de correo electrónico y arrojará el mismo error.
Esto se convierte en un dolor de cabeza, especialmente cuando se trata de sistemas grandes donde la restauración de registros es una tarea común.
Para evitar esto, podemos alterar temporalmente los valores de los campos únicos cuando se elimina temporalmente un registro y restaurar los valores originales cuando se recupera el registro. De esta manera, la base de datos no tropezará con la restricción única durante las eliminaciones o restauraciones temporales.
Un rasgo de Laravel es una excelente manera de encapsular esta funcionalidad. Aquí hay un rasgo que podemos usar para manejar el problema:
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(); }); } }
Este rasgo hace un par de cosas:
Así es como puedes aplicar este rasgo en tu modelo de Laravel:
class User extends Model { use SoftDeletes, AvoidDuplicateConstraintSoftDelete; // Specify which columns should avoid the unique constraint issue public function getDuplicateAvoidColumns(): array { return ['email', 'username']; } }
Al agregar el rasgo **AvoidDuplicateConstraintSoftDelete** a su modelo y especificar qué columnas deben evitar conflictos de restricciones únicas (como correo electrónico y nombre de usuario), puede prevenir fácilmente estos problemas .
Lo que eso significa es que, en el caso de un registro de eliminación temporal, no causaría un conflicto con operaciones posteriores debido a algunas restricciones únicas. O, en otras palabras, de esta manera podrá, al agregar la marca de tiempo a campos únicos, hacer que el registro esté “oculto” para la base de datos en términos de unicidad, pero aún así recuperable cuando sea necesario.
Esto es bastante útil cuando se trata de una base de datos grande y la restauración de registros es bastante común. No tendrás que lidiar siempre con el error de “entrada duplicada” cada vez que traigas un usuario eliminado temporalmente o cualquier otro modelo.
Lo más útil en Laravel es SoftDelete, pero a veces da dolores de cabeza al trabajar con restricciones únicas. Aquí viene una solución simple basada en rasgos que brindará una forma elegante de evitar el problema, simplemente mediante cambios temporales de campos únicos al eliminarlos y restaurarlos posteriormente. De esta manera evitará errores frustrantes y permitirá que su aplicación funcione sin problemas sin romper las restricciones únicas de su base de datos.
Si alguno de tus campos se ha hecho multilingüe o utiliza bibliotecas como Spatie's Translatable, la solución anterior funcionará sin problemas en cada uno de estos casos. Los SoftDeletes están destinados a brindarle flexibilidad, no a interponerse en su camino. Con la solución menor anterior implementada, evitará la mayoría de los problemas y mantendrá sus datos ordenados y a sus usuarios contentos.
Al agregar esta característica a sus modelos, se ahorrará tiempo y dolores de cabeza, especialmente si se trata de grandes conjuntos de datos donde la eliminación temporal y la restauración son operaciones frecuentes. Pruébelo en su proyecto Laravel y verá con qué facilidad maneja esos complicados problemas de restricciones únicas.
¡Gracias por leer! No olvide suscribirse para mantenerse informado sobre las últimas actualizaciones en diseño de sistemas e innovaciones en comercio electrónico. ¡Feliz diseño!
Si este artículo te resultó revelador y quieres mantenerte actualizado con más contenido sobre diseño de sistemas y tendencias tecnológicas, asegúrate de seguirme en :-
Twitter: https://twitter.com/hafiqdotcom
LinkedIn: https://www.linkedin.com/in/hafiq93
Cómprame café: https://paypal.me/mhi9388 /
https://buymeacoffee.com/mhitech
Medio: https://medium.com/@hafiqiqmal93
Descargo de responsabilidad: Todos los recursos proporcionados provienen en parte de Internet. Si existe alguna infracción de sus derechos de autor u otros derechos e intereses, explique los motivos detallados y proporcione pruebas de los derechos de autor o derechos e intereses y luego envíelos al correo electrónico: [email protected]. Lo manejaremos por usted lo antes posible.
Copyright© 2022 湘ICP备2022001581号-3