Удаление родительской модели Laravel не запускает событие удаления дочерней модели - PullRequest
0 голосов
/ 20 мая 2018

Я использую Laravel 5.4.У меня есть модель проекта в качестве родителя и модель project_images как дочерняя, а вот дочерняя модель:

Schema::create('project_images', function (Blueprint $table) {
            $table->increments('id');
            $table->integer('project_id')->unsigned();
            $table->foreign('project_id')->references('id')->on('projects')->onDelete('cascade');
            $table->string('file', 100);
            $table->timestamps();
        });

, поэтому, как и следовало ожидать, всякий раз, когда я удаляю проект, все его записи изображений также удаляются.Затем я создал событие удаления в модели images следующим образом:

protected $events = [
    'deleted' => ProjectImageDeleting::class
];

Если я удаляю само изображение, то это событие также запускается, но если я удаляю проект, то нет.

Мой вопрос

Как мне сделать так, чтобы при удалении родителя также запускалось дочернее событие?Я что-то пропустил? (у меня уже есть событие и слушатель, и код в слушателе работает, когда я удаляю изображение)

Обновление

Я удалил эту строку в миграциии изменил модель проекта на это:

namespace AliMHZ;

use Illuminate\Database\Eloquent\Model;

class Project extends Model
{
    public function images()
    {
        return $this->hasMany(ProjectImage::class);
    }

    protected static function boot()
    {
        parent::boot();
        static::deleting(function($project) {
            $project->images()->delete();
        });
    }
}

, и это моя модель изображения:

namespace AliMHZ;

use Illuminate\Database\Eloquent\Model;
use AliMHZ\Events\ProjectImageDeleting;

class ProjectImage extends Model
{
    protected $events = [
        'deleting' => ProjectImageDeleting::class
    ];
    public function project()
    {
        return $this->belongsTo(Project::class);
    }
}

и событие:

namespace AliMHZ\Events;

use Illuminate\Broadcasting\Channel;
use Illuminate\Queue\SerializesModels;
use Illuminate\Broadcasting\PrivateChannel;
use Illuminate\Broadcasting\PresenceChannel;
use Illuminate\Foundation\Events\Dispatchable;
use Illuminate\Broadcasting\InteractsWithSockets;
use Illuminate\Contracts\Broadcasting\ShouldBroadcast;
use AliMHZ\ProjectImage;

class ProjectImageDeleting
{
    use Dispatchable,
        InteractsWithSockets,
        SerializesModels;

    public $image;
    public function __construct(ProjectImage $image)
    {
        $this->image = $image;
    }
    public function broadcastOn()
    {
        return new PrivateChannel('channel-name');
    }
}

и, наконец, вотслушатель:

namespace AliMHZ\Listeners;

use AliMHZ\Events\ProjectImageDeleting;
use Illuminate\Queue\InteractsWithQueue;
use Illuminate\Contracts\Queue\ShouldQueue;

class ProjectImageDeletingListener
{
    public function __construct()
    {
        //
    }
    public function handle(ProjectImageDeleting $event)
    {
        \Log::info("File to be deleted: " . $event->image->file);
    }
}

После этих изменений, когда я удаляю проект, все его изображения также будут удалены, но событие изображения все еще не запускается, но если удалить только изображение, то событие работает.Я тестирую это в Laravel Tinker, и каждый раз, когда я меняю любую модель, я выхожу из Tinker и снова обедаю.

1 Ответ

0 голосов
/ 20 мая 2018

Когда вы используете $table->foreign('project_id')->references('id')->on('projects')->onDelete('cascade');, удаление выполняется на уровне базы данных, и, таким образом, события модели не запускаются.

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

<?php

class Project extends Eloquent
{
    public function images()
    {
        return $this->has_many('Image');
    }

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

        static::deleting(function($project) {
             // This will trigger the ProjectImageDeleting event.
             $project->images()->delete();
        });
    }
}

Отредактировано для ответа на отредактированную часть вопроса

Не могли бы вы попробовать следующее

namespace AliMHZ;

use Illuminate\Database\Eloquent\Model;

class Project extends Model
{
    public function images()
    {
        return $this->hasMany(ProjectImage::class);
    }

    protected static function boot()
    {
        parent::boot();
        static::deleting(function($project) {
            $project->images()->get()->each(function ($image) {
                  $image->delete();
            });
        });
    }
}

Если вы хотите узнать больше о том, почему это происходит, вы можете прочитать об этом в об этой проблеме на GitHub .

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...