«Если рабочий хочет хорошо выполнять свою работу, он должен сначала заточить свои инструменты» — Конфуций, «Аналитики Конфуция. Лу Лингун»
титульная страница > программирование > Laravel SoftDelete: решение проблемы уникального ограничения

Laravel SoftDelete: решение проблемы уникального ограничения

Опубликовано 6 ноября 2024 г.
Просматривать:625

Laravel SoftDelete: Avoiding the Unique Constraint Problem

Источник этой статьи: https://medium.com/@hafiqiqmal93/laravel-softdelete-avoiding-the-unique-constraint-problem-45381d9745a0

Если вы какое-то время используете Laravel, особенно когда проекты связаны с целостностью данных, скорее всего, вы уже сталкивались с функцией SoftDelete. Довольно полезно, поскольку вы можете «удалять» записи, не удаляя их из базы данных. Laravel просто добавляет метку времени delete_at, чтобы отметить его как удаленный, но он остается в системе. Это все хорошо для сохранения исторических данных, но при этом возникает одна потенциально неприятная проблема — что происходит с уникальными ограничениями при восстановлении обратимо удаленных записей?


Это становится проблемой, когда вы хотите восстановить запись, которая уже имеет, например, уникальный адрес электронной почты или имя пользователя в базе данных. Laravel просто выдаст ошибку и остановит процесс. К счастью, есть простой способ избежать этой проблемы.

Давайте рассмотрим решение, использующее особенность, которая поможет вам обойти уникальные ограничения при использовании SoftDelete в Laravel.

Понимание проблемы

Давайте рассмотрим простой пример. Представьте, что у вас есть таблица пользователей с полем электронной почты, которое должно быть уникальным:


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();
        });
    }
}


Эта черта выполняет несколько функций:

  • При удалении к уникальному полю добавляется временная метка, что, по сути, снова делает поле уникальным, не затрагивая исходное значение. Этот трюк полезен для сохранения уникальных ограничений во время мягкого удаления записи.
  • При восстановлении удаляется временная метка, восстанавливая исходное значение уникального поля.

Как это работает:

  • Обработка уникальных полей: всякий раз, когда модель с этим признаком удаляется, этот признак добавляет метку времени к полям, которые вы хотите сохранить уникальными (например: адрес электронной почты, имя пользователя). Это предотвращает конфликты, если вы попытаетесь добавить новую запись с теми же уникальными значениями.
  • Обработка переводимых полей: Если ваша модель использует библиотеку Spatie Translatable, эта черта достаточно умна, чтобы обрабатывать и многоязычные поля. Он ищет переводимые атрибуты, корректирует их значения и сохраняет их с помощью трюка с меткой времени.
  • Восстановление: Когда вы восстанавливаете обратимо удаленную запись, эта черта удаляет метку времени из уникальных полей, возвращая полю исходное значение.

Применение признака к вашей модели

Вот как вы можете применить эту черту в своей модели Laravel:


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


Добавив признак **AvoidDuplateConstraintSoftDelete** в свою модель и указав, какие столбцы должны избегать конфликтов уникальных ограничений (например, email и имя пользователя), вы можете легко предотвратить эти проблемы. .

Почему этот подход работает?

Это означает, что в случае обратимого удаления записи это не вызовет конфликта с дальнейшими операциями из-за некоторых уникальных ограничений. Другими словами, таким образом вы сможете, добавив временную метку к уникальным полям, сделать запись «скрытой» для базы данных с точки зрения уникальности, но при этом ее можно будет восстановить при необходимости.

Это весьма полезно, когда вы имеете дело с большой базой данных и восстановление записей является довольно распространенным явлением. Вам не придется каждый раз сталкиваться с ошибкой «дубликат записи», когда вы добавляете обратимо удаленного пользователя или любую другую модель.


Заключительные мысли

Самая полезная вещь в Laravel — это SoftDelete, но иногда он доставляет головную боль при работе с уникальными ограничениями. Вот простое решение, основанное на признаках, которое даст элегантный способ избежать проблемы, просто временно изменяя уникальные поля при удалении и последующем восстановлении. Таким образом, вы избежите досадных ошибок и позволите вашему приложению работать бесперебойно, не нарушая уникальных ограничений в вашей базе данных.

Если какое-либо из ваших полей сделано многоязычным или используются такие библиотеки, как Spatie's Translatable, приведенное выше решение будет работать без проблем в каждом из этих случаев. SoftDeletes предназначены для того, чтобы дать вам гибкость, а не мешать вам. Внеся вышеуказанное незначительное исправление, вы избежите большинства ошибок, сохраните свои данные в порядке, а ваши пользователи будут довольны.


Добавив эту особенность в свои модели, вы сэкономите время и избавитесь от головной боли, особенно если вы имеете дело с большими наборами данных, где мягкое удаление и восстановление являются частыми операциями. Попробуйте его в своем проекте Laravel, и вы увидите, насколько гладко он справляется с этими сложными уникальными проблемами ограничений!


Спасибо, что читаете! Не забудьте подписаться, чтобы быть в курсе последних обновлений в области системного проектирования и инноваций в электронной коммерции. Приятного проектирования!

Если эта статья показалась вам познавательной и вы хотите быть в курсе новых новостей о дизайне систем и тенденциях в области технологий, обязательно подпишитесь на меня :-

Твиттер: https://twitter.com/hafiqdotcom
LinkedIn: https://www.linkedin.com/in/hafiq93
Купи мне кофе: https://paypal.me/mhi9388/
https://buymeacoffee.com/mhitech
Средний: https://medium.com/@hafiqiqmal93

Заявление о выпуске Эта статья воспроизводится по адресу: https://dev.to/afiqiqmal/laravel-softdelete-avoiding-the-Unique-conster-problem-8k2?1 Если есть какие-либо нарушения, пожалуйста, свяжитесь с [email protected], чтобы удалить его.
Последний учебник Более>

Изучайте китайский

Отказ от ответственности: Все предоставленные ресурсы частично взяты из Интернета. В случае нарушения ваших авторских прав или других прав и интересов, пожалуйста, объясните подробные причины и предоставьте доказательства авторских прав или прав и интересов, а затем отправьте их по электронной почте: [email protected]. Мы сделаем это за вас как можно скорее.

Copyright© 2022 湘ICP备2022001581号-3