Когда я удаляю строку, используя этот синтаксис:
$user->delete();
Есть ли способ прикрепить своего рода обратный вызов, чтобы он, например, делал это автоматически:
$this->photo()->delete();
Желательно внутри модельного класса.
Я считаю, что это идеальный вариант использования событий Eloquent ( http://laravel.com/docs/eloquent#model-events ). Вы можете использовать событие «удаление» для очистки:
class User extends Eloquent
{
public function photos()
{
return $this->has_many('Photo');
}
// this is a recommended way to declare event handlers
public static function boot() {
parent::boot();
static::deleting(function($user) { // before delete() method call this
$user->photos()->delete();
// do the rest of the cleanup...
});
}
}
Вы, вероятно, должны также поместить все это в транзакцию, чтобы обеспечить ссылочную целостность.
first()
в запрос, чтобы я мог получить доступ к модели-события, например,User::where('id', '=', $id)->first()->delete();
Источникforeach($user->photos as $photo)
,$photo->delete()
чтобы убедиться, что у каждого ребенка были удалены его дети на всех уровнях, а не только на одном, как это происходило по какой-то причине.Photos
имеетtags
и вы делаете то же самое вPhotos
модели (т.е. наdeleting
методе:),$photo->tags()->delete();
он никогда не получает триггер. Но если я сделаю этоfor
циклом и сделаю что-то вродеfor($user->photos as $photo) { $photo->delete(); }
этого, тоtags
также будет удален! просто к сведениюВы можете настроить это в своих миграциях:
$table->foreign('user_id')->references('id')->on('users')->onDelete('cascade');
Источник: http://laravel.com/docs/5.1/migrations#foreign-key-constraints
источник
Вы можете удалить все связанные фотографии перед тем, как фактически удалить пользователя.
Надеюсь, поможет.
источник
$this->photos()->delete()
.photos()
Возвращает объект конструктор запросов.Отношение в модели пользователя:
Удалить запись и связанные:
источник
Есть 3 подхода к решению этой проблемы:
1. Использование красноречивых событий при загрузке модели (ссылка: https://laravel.com/docs/5.7/eloquent#events )
2. Использование Eloquent Event Observers (ссылка: https://laravel.com/docs/5.7/eloquent#observers )
В вашем AppServiceProvider зарегистрируйте наблюдателя следующим образом:
Затем добавьте класс Observer следующим образом:
3. Использование ограничений внешнего ключа (ссылка: https://laravel.com/docs/5.7/migrations#foreign-key-constraints )
источник
Начиная с Laravel 5.2, в документации говорится, что обработчики событий такого типа должны быть зарегистрированы в AppServiceProvider:
Я даже предполагаю переместить их в отдельные классы вместо замыканий для лучшей структуры приложения.
источник
Eloquent::observe()
метод также доступен в 5.2 и может использоваться из AppServiceProvider.photos()
, вы также должны быть осторожны - этот процесс не УДАЛИТЬ внук , потому что вы не загружая модель. Вам нужно будет зациклитьphotos
(заметьте, нетphotos()
) и запуститьdelete()
метод на них как на моделях, чтобы инициировать события, связанные с удалением.Для этого лучше переопределить
delete
метод. Таким образом, вы можете включить транзакции БД в самdelete
метод. Если вы используете способ события, вам придетсяdelete
при каждом вызове покрывать вызов метода транзакцией БД.В твоей
User
модели.источник
В моем случае это было довольно просто, потому что мои таблицы базы данных - это InnoDB с внешними ключами с Cascade на Delete.
Таким образом, в этом случае, если ваша таблица фотографий содержит ссылку на внешний ключ для пользователя, все, что вам нужно сделать, это удалить отель, и очистка будет выполнена с помощью базы данных, база данных удалит все записи фотографий из данных. основание.
источник
Я бы перебрал всю коллекцию, отключив все перед удалением самого объекта.
вот пример:
Я знаю, что это не автоматически, но это очень просто.
Другой простой подход - предоставить модели метод. Как это:
Тогда вы можете просто позвонить туда, где вам нужно:
источник
Или вы можете сделать это, если хотите, просто другой вариант:
Обратите внимание, что если вы не используете соединение по умолчанию с laravel db, вам нужно сделать следующее:
источник
Чтобы уточнить выбранный ответ, если ваши отношения также имеют дочерние отношения, которые необходимо удалить, вы должны сначала извлечь все записи дочерних отношений, а затем вызвать
delete()
метод, чтобы их события удаления также запускались правильно.Вы можете сделать это легко с сообщениями более высокого порядка .
Вы также можете повысить производительность, запросив только столбец ID отношений:
источник
да, но, как @supersan указал выше в комментарии, если вы удалите () в QueryBuilder, событие модели не будет запущено, потому что мы не загружаем саму модель, а затем вызываем delete () для этой модели.
События запускаются, только если мы используем функцию удаления в экземпляре модели.
Итак, это существо сказало:
чтобы удалить теги записей при удалении пользователя, нам нужно выполнить итерацию
$user->posts
и вызвать$post->delete()
foreach($user->posts as $post) { $post->delete(); }
-> это вызовет событие удаления на постВ.С.
$user->posts()->delete()
-> это не сработает при удалении события post, потому что мы на самом деле не загружаем модель Post (мы запускаем только SQL-код:DELETE * from posts where user_id = $user->id
таким образом, модель Post даже не загружается)источник
Вы можете использовать этот метод в качестве альтернативы.
Что произойдет, это то, что мы возьмем все таблицы, связанные с таблицей пользователей, и удалим связанные данные, используя цикл
источник