Laravel Eloquent Каскадные удаления

Я использую Laravel 4.1 и пытаюсь выполнить каскадное удаление. Я делаю это, так как некоторые методы удаления удаляют связанные активы, хранящиеся на S3, поэтому полагаться на каскадное удаление БД не подходит.

Скажем, у меня есть модель входа, которая сама имеет изображение и многие связанные параметры, которые также имеют изображения, как показано ниже (сокращено для краткости).

class Entry extends Eloquent {
    public function image()
    {
        return $this->morphOne('Image', 'imageable');
    }

    public function options()
    {
        return $this->hasMany('Option');
    }

    protected static function boot() {
        parent::boot();

        static::deleting(function($entry) {
            $image = $entry->image;
            if($image !== null) {
                $image->delete();
            }

            $entry->options()->delete()
            //Option::where('entry_id', $entry->id)->delete(); This also doesn't work
        });
    }
}

class Option extends Eloquent {

    public function entry()
    {
        return $this->belongsTo('Entry');
    }

    public function image()
    {
         return $this->morphOne('Image', 'imageable');
    }

    protected static function boot() {
        parent::boot();

        static::deleting(function($option) {
            Log::info('Trying to delete an option object');
            $image = $option->image;

            if($image !== null) {
                $image->delete();
            }
        });
    }
}

Примечание. Я выполняю удаление, как рекомендовано в этом ответе.

Когда я вызываю $entry->delete(), он удалит изображение и саму запись, однако обработчик удаления никогда не вызывается для параметров (я не вижу его вывода в журнал). Однако, если вместо этого я использую следующее в функции удаления записей, все работает нормально.

foreach($entry->options as $option) {
    $option->delete();
}

Почему не работает $entry->options()->delete()? Это ошибка в Laravel или я ошибся?


person cubiclewar    schedule 28.03.2014    source источник


Ответы (2)


class Entry extends Eloquent {
    public function image()
    {
        return $this->morphOne('Image', 'imageable');
    }

    public function options()
    {
        return $this->hasMany('Option');
    }

    protected static function boot() {
        parent::boot();

        static::deleting(function($entry) {
            $image = $entry->image;
            if($image !== null) {
                $image->delete();
            }

            $entry->options->each(function($option) {
                $option->delete();
            });
            //Option::where('entry_id', $entry->id)->delete(); This also doesn't work
        });
    }
}

вы можете использовать «каждый» http://laravel.com/docs/eloquent#collections

person alioygur    schedule 28.03.2014
comment
Я пытался использовать каждый, но я не думаю, что это сильно отличается от использования foreach, вам все равно нужно перебирать каждый объект. Мне больше интересно, почему $entry-›options()-›delete не работает - person cubiclewar; 29.03.2014

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

Напишите: https://medium.com/asked-io/cascading-softdeletes-with-laravel-5-a1a9335a5b4d

Laravel/Lumen Soft Cascade Удалить и восстановить https://github.com/Askedio/laravel-soft-cascade

person raison    schedule 27.06.2019