"Si un trabajador quiere hacer bien su trabajo, primero debe afilar sus herramientas." - Confucio, "Las Analectas de Confucio. Lu Linggong"
Página delantera > Programación > Laravel SoftDelete: evitando el problema de la restricción única

Laravel SoftDelete: evitando el problema de la restricción única

Publicado el 2024-11-06
Navegar:552

Laravel SoftDelete: Avoiding the Unique Constraint Problem

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.

Comprender el problema

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.

La solución: utilizar un rasgo para evitar restricciones duplicadas

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:

  • Al eliminarlo, agrega una marca de tiempo al campo único, esencialmente haciendo que el campo vuelva a ser único sin afectar el valor original. Este truco es útil para mantener satisfechas las restricciones únicas mientras el registro se elimina temporalmente.
  • Al restaurar, elimina la marca de tiempo, restaurando el valor original del campo único.

Cómo funciona:

  • Manejo de campos únicos: cada vez que se elimina un modelo con este rasgo, el rasgo se encarga de agregar una marca de tiempo a los campos que desea mantener únicos (ejemplo: correo electrónico, nombre de usuario). Esto evita conflictos si intenta agregar un nuevo registro con los mismos valores únicos.
  • Manejo de campos traducibles: Si su modelo usa la biblioteca Spatie Translatable, este rasgo es lo suficientemente inteligente como para manejar campos multilingües también. Busca los atributos traducibles, ajusta sus valores y los guarda con el truco de la marca de tiempo.
  • Restauración: Cuando restauras un registro eliminado temporalmente, el rasgo elimina la marca de tiempo de los campos únicos, devolviendo el campo a su valor original.

Aplicar el rasgo a su modelo

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 .

¿Por qué funciona este enfoque?

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.


Pensamientos finales

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

Declaración de liberación Este artículo se reproduce en: https://dev.to/afiqiqmal/laravel-softdelete-avoiding-the-unique-constraint-problem-8k2?1 Si hay alguna infracción, comuníquese con [email protected] para eliminarla.
Último tutorial Más>

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