首页 > 解决方案 > 删除父级时的“已删除”事件

问题描述

我有 2 个模型:UserRole.

一个用户可以有很多角色。

一个角色可以有多个用户。

我在这两个模型之间有一个自定义的枢轴模型。这个自定义数据透视模型之所以存在,是因为它使用了一个特性来监听/记录诸如createdupdated、之类的事件deleted

假设我有一个名为moderator. 当我attach()(或detach())将该角色分配给 5 个用户时,它确实为数据透视表成功触发了 5 个created(或deleted)事件。

$roleModerator->users()->attach($anArrayOfFiveUsersHere);

到目前为止,一切都很好。

我的问题如下:当我删除moderator角色本身时,它确实删除了与该角色关联的所有数据透视行,但它不会deleted为每个删除的数据透视行触发任何事件。

预期行为:当我要求 Laravel 删除角色时,我希望 Laravel 为deleted它在数据透视表中删除的每一行触发事件。

环境:PHP 7.3 / Laravel 6

我注意到一件奇怪的事情,如果我将它添加到我的Role模型中:

    public static function boot()
    {
        parent::boot();
        static::deleting(function (self $model)
        {
            //$model->users()->detach(); // <-- this fails firing deleted events.
            //MyCustomPivot::query()->where('role_id', $model->id)->get()->each->delete(); // <-- this fails firing deleted events.
            $model->users()->sync([]); // <--- this works!
        });
    }

sync([])将很好地工作并触发尽可能多的deleted事件,因为它删除了数据透视行。

但是detach(),虽然它完成了同样的事情,但不会触发任何deleted事件。这是为什么?他们都来自InteractisWithPivotTable.php甚至sync()自称detach()

在此处输入图像描述

标签: phplaravel

解决方案


不是 100% 确定它适用于您的情况,但是根据Github 上的这个问题,您需要在模型中进行一些设置。

首先,确保您的表中有一个主键列并在您的数据透视模型上定义。

<?php

namespace App\Models;

use Illuminate\Database\Eloquent\Relations\Pivot;

class MyCustomPivot extends Pivot
{
    public $primaryKey   = "id";
    public $incrementing = true;
}

其次,确保在您的关系中包含您的自定义数据透视模型。

<?php

namespace App\Models;

use Illuminate\Database\Eloquent\Model;

class Role extends Model
{
    public function users()
    {
        return $this->belongsToMany(User::class)
            ->using(MyCustomPivot::class)
            ->withPivot('id');
    }
}

class User extends Model
{

    public function roles()
    {
        return $this->belongsToMany(Role::class)
            ->using(MyCustomPivot::class)
            ->withPivot('id');
    }
}

推荐阅读