eloquent - 每当在 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()
方法时不会触发突变器,所以我认为即使它正在工作,我也看不出有什么区别。有人提到了观察者的可能性,但我不知道什么是观察者我是菜鸟。
就是这样,如果有人能帮助我度过我现在所处的这个烂摊子,那对我来说真的很好。提前致谢。
解决方案
可以同时附加新角色并设置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);
我希望这会有所帮助。
推荐阅读
- angular - Angular 英雄教程第 2 课显示列表:添加点击事件处理程序
- javascript - 使用 getRowStyle 时丢失选择背景颜色
- string - csh/tcsh 如何查找特定字符串是否在变量/文件名中?
- java - Spring 如何自动创建/实例化存储库
- json - 如何在颤动中解密带有gzip编码数据的json响应?
- c# - NuGet:将包依赖项显式列出为项目中的包引用,以便可以卸载它们
- google-apps-script - 谷歌表格 - 在脚本中使用偏移量中的单元格值
- sql - I have a problem removing; of a column with the substring in SQL Server
- javascript - Mousemove events don't trigger
- asp.net - WebForm MVP one view to display different controls after each button click