genealabs/laravel-pivot-events

此包为 BelongsToMany 关系中的 sync()、attach()、detach() 或 updateExistingPivot() 方法引入了新的 Eloquent 事件。

11.0.0 2024-03-14 23:24 UTC

This package is auto-updated.

Last update: 2024-09-15 00:41:58 UTC


README

此包为 BelongsToMany 和 MorphToMany 关系中的 sync()、attach()、detach() 或 updateExistingPivot() 方法引入了新的 Eloquent 事件。

此包是 fico7489/laravel-pivot 的分支,主要为了解决与 Laravel TelescopeLaravel 模型缓存 的兼容性问题。

赞助商

感谢以下赞助商的慷慨。请花一点时间了解他们

要求

  • Laravel 8.0+
  • PHP 7.3+

安装

1. 使用 composer 安装包: composer require "genealabs/laravel-pivot-events:*"

  1. 在您的基模型或特定模型中使用 GeneaLabs\LaravelPivotEvents\Traits\PivotEventTrait 特性。
    // ...
    use GeneaLabs\LaravelPivotEvents\Traits\PivotEventTrait;
    use Illuminate\Database\Eloquent\Model;
    
    abstract class BaseModel extends Model
    {
        use PivotEventTrait;
        // ...
    }

新 Eloquent 事件

您可以在这里查看所有 Eloquent 事件:https://laravel.net.cn/docs/5.8/eloquent#events)

新事件有

  • pivotSyncing, pivotSynced
  • pivotAttaching, pivotAttached
  • pivotDetaching, pivotDetached
  • pivotUpdating, pivotUpdated

捕捉事件的最简单方法是使用模型中 boot() 方法的函数

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

    static::pivotSyncing(function ($model, $relationName) {
        //
    });
     
    static::pivotSynced(function ($model, $relationName, $changes) {
        //
    });

    static::pivotAttaching(function ($model, $relationName, $pivotIds, $pivotIdsAttributes) {
        //
    });
    
    static::pivotAttached(function ($model, $relationName, $pivotIds, $pivotIdsAttributes) {
        //
    });
    
    static::pivotDetaching(function ($model, $relationName, $pivotIds) {
        //
    });

    static::pivotDetached(function ($model, $relationName, $pivotIds) {
        //
    });
    
    static::pivotUpdating(function ($model, $relationName, $pivotIds, $pivotIdsAttributes) {
        //
    });
    
    static::pivotUpdated(function ($model, $relationName, $pivotIds, $pivotIdsAttributes) {
        //
    });
    
    static::updating(function ($model) {
        //this is how we catch standard eloquent events
    });
}

您还可以使用专用事件监听器来捕捉它们

\Event::listen('eloquent.*', function ($eventName, array $data) {
    echo $eventName;  //e.g. 'eloquent.pivotAttached'
});

支持的关系

BelongsToManyMorphToMany

哪些事件会被触发以及它们何时会被触发

四个 BelongsToMany 方法从这个包触发事件

attach()
触发一个 pivotAttaching 和一个 pivotAttached 事件。
即使添加了更多行,也只为所有行触发一个事件,但在这种情况下,您可以在 $pivotIds 变量中看到所有更改的行 ID,以及在 $pivotIdsAttributes 变量中看到带有属性的更改行 ID。

detach()
触发一个 pivotDetaching 和一个 pivotDetached 事件。
即使删除了更多行,也只为所有行触发一个事件,但在这种情况下,您可以在 $pivotIds 变量中看到所有更改的行 ID。

updateExistingPivot()
触发一个 pivotUpdating 和一个 pivotUpdated 事件。
您只能使用 updateExistingPivot 更改枢纽表中的一行。

sync()
触发一个 pivotSyncing 和一个 pivotSynced 事件。
在同步过程中,是否为行添加/删除/更新只触发一个事件,但在这种情况下,您可以在 $changes 变量中看到所有已添加/删除/更新的行。
例如 sync 的工作原理: sync 首先断开所有关联,然后逐个添加或更新新条目。

用法

数据库中有三个表:users(id, name),roles(id, name),role_user(user_id, role_id)。我们有两个模型

class User extends Model
{
    use PivotEventTrait;
    // ...

    public function roles()
    {
        return $this->belongsToMany(Role::class);
    }

    static::pivotSynced(function ($model, $relationName, $changes) {
        echo 'pivotSynced';
        echo get_class($model);
        echo $relationName;
        print_r($changes);
    });    

    static::pivotAttached(function ($model, $relationName, $pivotIds, $pivotIdsAttributes) {
        echo 'pivotAttached';
        echo get_class($model);
        echo $relationName;
        print_r($pivotIds);
        print_r($pivotIdsAttributes);
    });
    
    static::pivotUpdated(function ($model, $relationName, $pivotIds, $pivotIdsAttributes) {
        echo 'pivotUpdated';
        echo get_class($model);
        echo $relationName;
        print_r($pivotIds);
        print_r($pivotIdsAttributes);
    });

    static::pivotDetached(function ($model, $relationName, $pivotIds) {
        echo 'pivotDetached';
        echo get_class($model);
        echo $relationName;
        print_r($pivotIds);
    });

    // ...
}
class Role extends Model
{
    // ...
}

附加

对于 attach() 或 detach(),为每个枢纽 ID 触发一个事件。

使用主键附加

运行此代码

$user = User::first();
$user->roles()->attach(1);

您将看到以下输出

pivotAttached
App\Models\User
roles
[1]
[1 => []]

使用数组附加

运行此代码

$user = User::first();
$user->roles()->attach([1]);

您将看到以下输出

pivotAttached
App\Models\User
roles
[1]
[1 => []]

使用模型附加

运行此代码

$user = User::first();
$user->roles()->attach(Role::first());

您将看到以下输出

pivotAttached
App\Models\User
roles
[1]
[1 => []]

使用集合附加

运行此代码

$user = User::first();
$user->roles()->attach(Role::get());

您将看到以下输出

pivotAttached
App\Models\User
roles
[1, 2]
[1 => [], 2 => []]

使用数组附加 (id => 属性)

运行此代码

$user = User::first();
$user->roles()->attach([1, 2 => ['attribute' => 'test']], ['attribute2' => 'test2']);

您将看到以下输出

pivotAttached
App\Models\User
roles
[1, 2]
[1 => [], 2 => ['attribute' => 'test', 'attribute2' => 'test2']]

同步

运行此代码

$user = User::first();
$user->roles()->attach([
     1 => ['pivot_attribut' => 1],
     2 => ['pivot_attribut' => 0]
 ]);
 $user->roles()->sync([
     1 => ['pivot_attribut' => 0]
     3 => ['pivot_attribut' => 1]
 ]);

您将看到以下输出

pivotSynced
App\Models\User
roles
[
   "attached" => [
     0 => 3
   ]
   "detached" => [
     1 => 2
   ]
   "updated" => [
     0 => 1
   ]
 ]

解除附加

运行此代码

$user = User::first();
$user->roles()->detach([1, 2]);

您将看到以下输出

pivotAttached
App\Models\User
roles
[1, 2]

更新

运行此代码

$user = User::first();
$user->roles()->updateExistingPivot(1, ['attribute' => 'test']);

您将看到以下输出

pivotUpdated
App\Models\User
roles
[1]
[1 => ['attribute' => 'test']]