Изменение столбца, которое повлияло на другие столбцы

#laravel #eloquent

#laravel #красноречивый

Вопрос:

У меня есть следующая таблица:

 $table->boolean('prop_enabled');
$table->boolean('prop1_enabled')->nullable();
$table->boolean('prop2_enabled')->nullable();
$table->boolean('prop3_enabled')->nullable();
  

Мое требование заключается в том, что когда prop_enabled false , тогда prop1_enabled prop2_enabled и prop3_enabled значения должны быть установлены null во время вставки или обновления строки.

Подходит ли мой дизайн таблицы для решения проблемы? Если моя таблица подходит для решения проблемы, какой подход лучше подходит для выполнения моих требований? У меня есть варианты создания триггера в базе данных или переопределения Create и save метода из Model класса.

Комментарии:

1. вам не нужно будет переопределять эти методы, в моделях есть события, которые вы можете прослушивать, например saving , событие

2. Спасибо @lagbox, если я использую прослушиватель событий, будет ли 2 запроса для каждого создания? 1-й для создания строки, 2-й запрос для обновления новой строки на основе столбца prop_enabled

3. нет… saving выполняется до сохранения модели

4. вы также можете просто игнорировать другие поля независимо от их значений в базе данных, когда prop_enabled значение false с помощью mutator . Что будет менее тяжелым для производительности и позволит избежать проблем, связанных с массовым назначением и методами вставки / обновления в обход модели

Ответ №1:

Я считаю, что лучшим подходом является решение Observer. Использование мутатора требует большого количества мутаторов для защиты вашей структуры данных и / или бизнес-логики, которые могут его игнорировать. Наблюдатель использует события, и вы можете только обойти его запуск, избегая использования eloquent.

Вы можете подключиться к saving событию в моделях. Это позволит просмотреть модель перед ее сохранением, затем изменить ее, если ваш случай верен, и тем самым создать оптимальную вставку запроса 1. Независимо от того, какова ваша бизнес-логика, это сработает перед созданием или обновлением.

 class YourModelObserver {
    public function saving(YourModel $model) {
        if ($model->prop_enabled === false) {
            $model->prop1_enabled = false;
            $model->prop2_enabled = false;
            $model->prop3_enabled = false;
        }
    }
}
  

В провайдере вы должны зарегистрировать своего слушателя.

 public function boot()
{
    YourModel::observe(YourModelObserver::class);
}
  

Моя самая большая проблема с вашим дизайном — это обычный запах кода, который я видел раньше. Именование переменных после чисел, когда у вас их несколько, мне кажется неправильным. Что произойдет, если вы получите 4. prop и как вы будете их показывать и обновлять? Альтернативным подходом было бы иметь их в более общем виде в другой таблице, когда у них было имя или ключ вместо того, чтобы быть prop1 или prop2 и иметь логику, связанную с их созданием или обновлением. Если вы уверены, что prop1, prop2 и prop3 не изменят дизайн, это хорошо на данный момент.

Комментарии:

1. Спасибо @mrhn за вашу поддержку и ваш комментарий по поводу запаха кода. Я просто хочу сделать свойство более общим, я бы не стал использовать это наименование в проекте.

2. К вашему сведению, в текущем проекте, над которым я работаю, у них были свойства person1, person2 и person3, и это создало столько проблем, что оно было разработано именно так.