I'd like to listen for events for Eloquent model that use HasRole or HasPermissions traits.
Examples:
Code sample:
`class User {
use HasRoles;
protected $dispatchesEvents = [
'role_assigned' => RoleAssigned::class,
'role_revoked' => RoleRevoked::class
];`
Is it possibile?
You might find the proposed customizations in https://github.com/spatie/laravel-permission/pull/724 useful for your situation.
Thank you
I found the easiest way was to overload the trait, in this example i'm using Spatie's activity logger to log every action:
namespace App\Models\Traits;
use Illuminate\Support\Facades\Auth;
use Spatie\Permission\Traits\HasRoles;
/**
* @mixin \App\Models\BaseModel
*/
trait HasRolesTrait
{
use HasRoles {
assignRole as protected originalAssignRole;
removeRole as protected originalRemoveRole;
syncRoles as protected originalSyncRoles;
}
/**
* @param mixed ...$roles
* @return $this
*/
public function assignRole(...$roles)
{
$this->originalAssignRole(...$roles);
$this->logRoleAssigned($roles);
return $this;
}
/**
* @param $role
* @return bool
*/
public function logRoleAssigned($role): bool
{
if (is_array($role)) {
return array_walk($role, [$this, 'logRoleAssigned']);
}
$role = $this->getStoredRole($role);
activity()
->useLog('role_assigned')
->causedBy(Auth::user())
->performedOn($this)
->withProperties([
'role_name' => $role->name
])
->log(':subject.name was assigned the role :properties.role_name by :causer.name');
return true;
}
/**
* @param $role
*/
public function removeRole($role)
{
$this->originalRemoveRole($role);
}
/**
* @param $role
* @return bool
*/
public function logRoleRemoved($role): bool
{
if (is_iterable($role)) {
return array_walk($role, [$this, 'logRoleRemoved']);
}
$role = $this->getStoredRole($role);
activity()
->useLog('role_removed')
->causedBy(Auth::user())
->performedOn($this)
->withProperties([
'role_name' => $role->name
])
->log(':subject.name was removed from the role :properties.role_name by :causer.name');
return true;
}
}
You could quite easily use the same method to fire events instead:
namespace App\Models\Traits;
use Spatie\Permission\Traits\HasRoles;
/**
* @mixin \App\Models\BaseModel
*/
trait HasRolesTrait
{
use HasRoles {
assignRole as protected originalAssignRole;
removeRole as protected originalRemoveRole;
syncRoles as protected originalSyncRoles;
}
/**
* @param mixed ...$roles
* @return $this
*/
public function assignRole(...$roles)
{
$this->originalAssignRole(...$roles);
$this->fireRoleAssignedEvent($roles);
return $this;
}
/**
* @param $role
* @return bool
*/
public function fireRoleAssignedEvent($role)
{
if (is_iterable($role)) {
return array_walk($role, [$this, 'fireRoleAssignedEvent']);
}
event(new RoleAssignedEvent($this, $this->getStoredRole($role)));
return true;
}
/**
* @param $role
* @return $this
*/
public function removeRole($role)
{
$this->originalRemoveRole($role);
$this->fireRoleRemovedEvent($role);
return $this;
}
/**
* @param $role
* @return bool
*/
public function fireRoleRemovedEvent($role)
{
if (is_iterable($role)) {
return array_walk($role, [$this, 'fireRoleRemovedEvent']);
}
event(new RoleRemovedEvent($this, $this->getStoredRole($role)));
return true;
}
}
Thank you @robjbrain
Most helpful comment
You could quite easily use the same method to fire events instead: