Este artigo foi originado de https://medium.com/@hafiqiqmal93/laravel-softdelete-avoiding-the-unique-constraint-problem-45381d9745a0
Caso você já use o Laravel há algum tempo, especialmente quando projetos envolvem integridade de dados, provavelmente você já encontrou o recurso SoftDelete. Muito útil porque você pode “excluir” registros sem realmente retirá-los do banco de dados. O que o Laravel faz é apenas adicionar um carimbo de data e hora excluído_at para marcá-lo como excluído, mas permanece no sistema. É muito bom reter dados históricos, mas introduz um problema potencialmente complicado - o que acontece com restrições exclusivas quando você restaura registros excluídos de forma reversível?
Isso se torna um problema quando você deseja restaurar um registro que já possui, por exemplo, um email ou nome de usuário exclusivo, no banco de dados. O Laravel irá apenas gerar um erro e interromper o processo. Felizmente, existe uma maneira fácil de evitar esse problema de uma maneira muito limpa.
Vamos percorrer uma solução usando uma característica que o ajudará a contornar as restrições exclusivas ao usar SoftDelete no Laravel.
Vamos dar um exemplo básico. Imagine que você tem uma tabela de usuários com um campo de email que deve ser exclusivo:
Schema::create('users', function (Blueprint $table) { $table->string('email')->unique(); $table->softDeletes(); });
Se você excluir um usuário com o e-mail [email protected] e depois criar um novo usuário com o mesmo e-mail, o Laravel reclamará da restrição exclusiva no campo de e-mail, gerando um erro. Na mesma situação, ao tentar restaurar o usuário excluído, o Laravel também irá reclamar da restrição exclusiva no campo email e gerar o mesmo erro.
Isso se torna uma dor de cabeça, especialmente quando se trata de grandes sistemas onde a restauração de registros é uma tarefa comum.
Para evitar isso, podemos alterar temporariamente os valores de campos exclusivos quando um registro é excluído de forma reversível e restaurar os valores originais quando o registro é recuperado. Dessa forma, o banco de dados não tropeça na restrição exclusiva durante exclusões suaves ou restaurações.
Uma característica do Laravel é uma ótima maneira de encapsular essa funcionalidade. Aqui está uma característica que podemos usar para lidar com o 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(); }); } }
Essa característica faz algumas coisas:
Veja como você pode aplicar essa característica em seu modelo Laravel:
class User extends Model { use SoftDeletes, AvoidDuplicateConstraintSoftDelete; // Specify which columns should avoid the unique constraint issue public function getDuplicateAvoidColumns(): array { return ['email', 'username']; } }
Ao adicionar a característica **AvoidDuplicateConstraintSoftDelete** ao seu modelo e especificar quais colunas precisam evitar conflitos de restrição exclusivos (como e-mail e nome de usuário), você pode facilmente evitar esses problemas .
O que isso significa é que, no caso de um registro de exclusão reversível, isso não causaria conflito com operações adicionais devido a algumas restrições exclusivas. Ou, em outras palavras, desta forma você poderá, anexando o carimbo de data/hora aos campos únicos, tornar o registro “oculto” para o banco de dados em termos de exclusividade, mas ainda recuperável quando necessário.
Isso é bastante útil quando você está lidando com um grande banco de dados e a restauração de registros é bastante comum. Você não terá que lidar sempre com o erro de “entrada duplicada” sempre que trouxer um usuário excluído de forma reversível ou qualquer outro modelo.
A coisa mais útil no Laravel é o SoftDelete, mas às vezes dá dor de cabeça ao trabalhar com restrições únicas. Aí vem uma solução simples e baseada em características que fornecerá uma maneira elegante de evitar o problema, apenas por meio de alterações temporárias de campos exclusivos na exclusão e restauração posterior. Dessa forma, você evitará erros frustrantes e permitirá que seu aplicativo funcione perfeitamente, sem quebrar restrições exclusivas em seu banco de dados.
Se algum de seus campos for multilíngue ou fizer uso de bibliotecas como Spatie’s Translatable, a solução acima funcionará sem problemas em cada um desses casos. Os SoftDeletes foram criados para oferecer flexibilidade e não atrapalhar. Com a pequena correção acima implementada, você evitará a maioria das armadilhas e manterá seus dados organizados e seus usuários satisfeitos.
Ao adicionar essa característica aos seus modelos, você economizará tempo e dores de cabeça, especialmente se estiver lidando com grandes conjuntos de dados onde a exclusão reversível e a restauração são operações frequentes. Experimente em seu projeto Laravel e você verá como ele lida facilmente com esses problemas complicados de restrições únicas!
Obrigado por ler! Não se esqueça de se inscrever para se manter informado sobre as últimas atualizações em design de sistemas e inovações em comércio eletrônico. Feliz design!
Se você achou este artigo esclarecedor e deseja se manter atualizado com mais conteúdo sobre design de sistemas e tendências tecnológicas, siga-me em :-
Twitter: https://twitter.com/hafiqdotcom
LinkedIn: https://www.linkedin.com/in/hafiq93
Compre café para mim: https://paypal.me/mhi9388 /
https://buymeacoffee.com/mhitech
Médio: https://medium.com/@hafiqiqmal93
Isenção de responsabilidade: Todos os recursos fornecidos são parcialmente provenientes da Internet. Se houver qualquer violação de seus direitos autorais ou outros direitos e interesses, explique os motivos detalhados e forneça prova de direitos autorais ou direitos e interesses e envie-a para o e-mail: [email protected]. Nós cuidaremos disso para você o mais rápido possível.
Copyright© 2022 湘ICP备2022001581号-3