本文源自https://medium.com/@hafiqiqmal93/laravel-softdelete-avoiding-the-unique-constraint-problem-45381d9745a0
如果您已经使用 Laravel 一段时间,特别是当项目涉及数据完整性时,您很可能已经遇到过 SoftDelete 功能。非常有用,因为您可以“删除”记录,而无需真正将它们从数据库中取出。 Laravel 所做的只是添加一个deleted_at 时间戳,以便将其标记为已删除,但仍保留在系统中。保留历史数据固然很好,但它确实引入了一个潜在的棘手问题——当您恢复软删除记录时,唯一约束会发生什么情况?
当您想要恢复数据库中已有的记录(例如唯一的电子邮件或用户名)时,这就会成为问题。 Laravel 只会抛出一个错误并停止进程。幸运的是,有一种简单的方法可以非常干净地避免这个问题。
让我们使用一个特性来演示一个解决方案,该特性将帮助您绕过在 Laravel 中使用 SoftDelete 时的独特约束。
让我们举一个基本的例子。假设您有一个用户表,其中的电子邮件字段必须是唯一的:
Schema::create('users', function (Blueprint $table) { $table->string('email')->unique(); $table->softDeletes(); });
如果您软删除电子邮件地址为 [email protected] 的用户,然后使用同一电子邮件地址创建一个新用户,Laravel 会抱怨电子邮件字段的唯一约束,并引发错误。在同样的情况下,当你尝试恢复已删除的用户时,Laravel 也会抱怨电子邮件字段的唯一约束并抛出相同的错误。
这变得令人头痛,尤其是在处理记录恢复是一项常见任务的大型系统时。
为了防止这种情况,我们可以在软删除记录时临时更改唯一字段的值,并在恢复记录时恢复原始值。这样,数据库在软删除或恢复期间就不会超出唯一约束。
Laravel 特征是封装此功能的好方法。这是我们可以用来处理问题的一个特征:
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(); }); } }
这个特质有几件事:
以下是如何在 Laravel 模型中应用此特征的方法:
class User extends Model { use SoftDeletes, AvoidDuplicateConstraintSoftDelete; // Specify which columns should avoid the unique constraint issue public function getDuplicateAvoidColumns(): array { return ['email', 'username']; } }
通过将 **AvoidDuplicateConstraintSoftDelete** 特征添加到模型中并指定哪些列需要避免唯一约束冲突(例如 email 和 username),您可以轻松防止这些问题.
这意味着,在软删除记录的情况下,由于某些独特的约束,不会导致与进一步操作的冲突。或者,换句话说,通过这种方式,您将能够通过将时间戳附加到唯一字段,使数据库的记录在唯一性方面“隐藏”,但在需要时仍然可以恢复。
当您处理大型数据库并且记录恢复很常见时,这非常有用。每当您引入软删除用户或任何其他模型时,您不必每次都处理“重复条目”错误。
Laravel 中最有用的东西是 SoftDelete,但有时它在处理独特约束时会让人头疼。这里有一个简单的、基于特征的解决方案,它将提供一种避免问题的优雅方法,只需在删除和恢复时临时更改唯一字段即可。这样您将避免令人沮丧的错误,并让您的应用程序顺利工作,而不会破坏数据库中的唯一约束。
如果您的任何领域已实现多语言化或使用 Spatie 的 Translatable 等库,则上述解决方案在每种情况下都可以正常工作。 SoftDeletes 旨在为您提供灵活性,而不是妨碍您。通过上述小修复,您将避免大多数陷阱并保持数据整洁和用户满意。
通过将此特征添加到您的模型中,您将节省时间并减少麻烦,特别是当您处理软删除和恢复是频繁操作的大型数据集时。在你的 Laravel 项目中尝试一下,你会发现它如何顺利地处理那些棘手的独特约束问题!
感谢您的阅读!不要忘记订阅以随时了解系统设计和电子商务创新的最新动态。设计愉快!
如果您发现本文富有洞察力,并希望了解有关系统设计和技术趋势的更多内容,请务必关注我:-
推特:https://twitter.com/hafiqdotcom
领英:https://www.linkedin.com/in/hafiq93
给我买咖啡:https://paypal.me/mhi9388 /
https://buymeacoffee.com/mhitech
媒体:https://medium.com/@hafiqiqmal93
免責聲明: 提供的所有資源部分來自互聯網,如果有侵犯您的版權或其他權益,請說明詳細緣由並提供版權或權益證明然後發到郵箱:[email protected] 我們會在第一時間內為您處理。
Copyright© 2022 湘ICP备2022001581号-3