首页 > 解决方案 > 每当在 laravel 中发生记录插入或更新时,在数据透视表中设置一个字段

问题描述

好的,最近我在 laravel 中实现了一个基于 RBAC 的系统。

我有这两个类作为我的模型:

class User extends Authenticatable
{
    public function roles(){
        return $this->belongsToMany(\App\Role::class, 'user_role', 'user_id', 'role_id')->withPivot('is_expired', 'assigned_at', 'expire_at');
    }
}

class Role extends Model
{
    public function users(){
        return $this->belongsToMany(\App\User::class, 'user_role', 'role_id', 'user_id')->withPivot('is_expired', 'assigned_at', 'expire_at');
    }
}

它工作正常但是,我想expire_at根据模型的属性为数据透视表的属性设置一个默认值Role。例如,我period在表上有一个属性Roles,它是一个代表月数的数字。所以我想当分配给用户的角色(插入数据透视表中)expire_at设置为currentDatetime + thePeriodNum月份的值并保存在数据透视表中。

我怎样才能做到这一点?

我已经尝试过 laravel 自定义枢轴类和变异器,但它似乎不起作用或者我做错了什么。有人提到使用attach()/detach()方法时不会触发突变器,所以我认为即使它正在工作,我也看不出有什么区别。有人提到了观察者的可能性,但我不知道什么是观察者我是菜鸟。

就是这样,如果有人能帮助我度过我现在所处的这个烂摊子,那对我来说真的很好。提前致谢。

标签: eloquentlaravel-6eloquent-relationship

解决方案


可以同时附加新角色并设置expires_at列。这将避免需要在您的代码中使用观察者(模型事件的侦听器)。

代码如下所示:

$role = Role::find($roleId);

$expireAt = now()->addMonths($role->period)->toDateTimeString();

// or Carbon::now()->addMonths($role->period)->toDateTimeString();

User::find($userId)->roles()->attach($role->id, ['expire_at' => $expireAt]);

在这里,找到了角色。时间戳是通过获取当前时间创建的,添加基于角色的附加月份period(这应该是一个整数值)。

最后,将其添加到用户的角色附件中。

添加为模型方法

这都可以作为User模型上的函数/方法添加,它将代码清理为一个动作,->addRole($roleId)

// Within App\User.php

public function addRole($roleId)
{
    $role = \App\Role::find($roleId);

    $expiresAt = now()->addMonths($role->period)->toDateTimeString();

    $this->roles()->attach($role->id, [ 'expire_at' => $expiresAt ]);
}

然后可以使用以下方法调用它:

$user = User::find($id);

$user->addRole($roleId);

我希望这会有所帮助。


推荐阅读