Laravel 删除父模型不会触发子模型删除事件
Laravel parent model deletion doesn't fire up child model deleting event
我正在使用 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 并再次午餐。
当您使用 $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();
});
});
}
}
如果您想详细了解为什么会发生这种情况,可以在 this issue on GitHub 上阅读。
我正在使用 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 并再次午餐。
当您使用 $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();
});
});
}
}
如果您想详细了解为什么会发生这种情况,可以在 this issue on GitHub 上阅读。