Как каскадировать на softdeletes в Laravel4?
пытался использовать внешние ключи с Delete cascade и softDeletes без особого успеха.
у меня есть 2 таблицы: пользователи, события. Обе таблицы имеют softDeletes.
пользователи могут иметь 0..N событий.
События имеют user_id, используемый в качестве внешнего ключа для пользователей, например:
$table->foreign('user_id')->references('id')->on('users')->onDelete('CASCADE')->onUpdate('CASCADE');
проблема в том, что когда я удаляю пользователя, он получает мягкое удаление, но его события-ни мягкое удаление, ни физическое удаление.
Я делаю что-то неправильно, или это правильное красноречивое поведение?
во-вторых, если это правильное поведение, как наилучшим образом реализовать каскадное удаление? возможно, переопределение метода delete () в моих моделях, подобных этому ...
public function delete()
{
//delete all events...
__parent::delete()
}
?
3 ответов
внешний ключ БД ничего не сделает, потому что вы не изменили первичный ключ в вопросе. Только при обновлении или удалении первичного ключа связанные строки будут изменены.
все, что я могу найти по этой теме, решение заключается в использовании красноречивого Модель Событий для прослушивания события удаления и обновления связанных таблиц.
вот один вопрос StackOverflow об этом.
кроме того, вы можете "продлить" the delete()
метод и включить в него функции непосредственно, а также. вот пример.
ты преувеличиваешь.
либо просто удалите события прямо перед удалением пользователей:
$user->events()->delete();
$user->delete();
или создайте функцию удаления клиента в пользовательской модели:
public function customDelete(){
$this->events()->delete();
return $this->delete();
}
вы также можете добавить наблюдателя модели и следить за событием удаления или удаления, но в сценарии, который вы упомянули выше, предыдущие два метода были бы более простыми решение.
если я правильно понимаю, вы пытаетесь каскадировать softdeletes в обеих таблицах?
Я считаю, что сделать это с помощью ON UPDATE CASCADE не является правильным подходом. Я попытаюсь объяснить почему...
чтобы даже попытаться сделать это, вам нужно создать отношения внешний ключ составной ключ.
ie вам нужно связать (события.user_id и deleted_at) в (Пользователь.id и delete_at). Если вы измените одну, она обновит другую.
Первый вы необходимо добавить правило по умолчанию к столбцам deleted_at, так как вы не можете ссылаться на значения null.
поэтому добавьте к вашим миграциям для обеих таблиц...
$table->softDeletes()->default('0000-00-00 00:00:00');
добавьте в таблицу пользователя уникальный ключ с помощью " id " и "deleted_at"
Schema::table('users; function($table) {
$table->unique(array('id','deleted_at'))
});
затем в таблице событий создайте внешний ключ, например (ссылки на уникальный ключ)
Schema::table('events; function($table) {
$table->foreign(array('user_id','deleted_at'),'events_deleted_at_foreign_key')->
}->references(array('id','deleted_at'))->on('users')->onUpdate('CASCADE'));
запустите это, теперь вы должны найти, если вы мягко удалите своего пользователя, он будет мягко удалить его события.
однако, если вы теперь попытаетесь мягко удалить событие, оно потерпит неудачу на ограничении внешнего ключа. Почему ты спрашиваешь??
Ну, что вы делаете, это создание родительских дочерних отношений с использованием id, deleted_at в обеих таблицах. Обновление родителя, будет обновлять ребенка. И отношения не прерываются. Однако если вы обновите ребенка, связь теперь нарушена, оставив ребенка сиротой в таблице. Это не позволяет сдерживать внешний ключ.
Sooo длинный запыхавшийся ответ, но, надеюсь, хорошее объяснение того, почему то, что вы пытаетесь сделать, не будет работать и сэкономить вам много времени, пытаясь сделать это с помощью каскада обновлений. Либо войдите в триггеры и запустите функцию для обработки того, что вы пытаетесь сделать, либо обработайте ее в своем приложении. Лично я бы сделал это с триггерами, чтобы база данных оставалась собственной сущностью и не полагалась ни на что, чтобы сохранить целостность данных.
delimiter //
создать Триггер soft_delete_child после обновления на БД.пользователи для каждой строки НАЧИНАТЬ ЕСЛИ НОВЫЙ.deleted_at старого.deleted_at тогда Обновить события SET deleted_at=NEW.deleted_at где события.user_id=новый.id; КОНЕЦ, ЕСЛИ; Конец;
// разделитель ;