Enums shouldn't be casted in the model
schnetzi opened this issue · 8 comments
Describe the bug
I am using an enum for my roles. It is called UserRoleEnum
. I somehow thought that I need to cast the enum when saving in the database. So I added the following to my Role
-Model
protected $casts = [
'name' => UserRoleEnum::class,
];
I know now that this was not needed/causes the package to not work correctly anymore.
Versions
- spatie/laravel-permission package version: 6.3.0
- laravel/framework package: v10.43.0
PHP version: 8.3.1
Database version: MySQL 8.2.0
To Reproduce
Steps to reproduce the behavior:
- Setup Laravel and the permission package
- Use an enum for the Role
- Cast the enum in the Model
- Assign a user any role
- Use
hasRole(UserRoleEnum::<ROLE>)
and it will always return false
Here is my example code and/or tests showing the problem in my app:
The first output are the user roles, the second one the name of the first role and the third one the hasRole
-check
Example Application
I didn't create one so far. If you prefer to have one I can set one up.
Expected behavior
I am not sure if it is a bug or a missing information in the documentation (I know that it should say not to cast but it would have saved me a few hours). Both would be valid fixes for me.
Environment (please complete the following information, because it helps us investigate better):
- OS: macOS
- Version 14.2.1
Instead of $users[0]->hasRole(UserRoleEnum::ADMIN->value)
, does it work if you remove the -value
part? (because it does that internally)
Instead of
$users[0]->hasRole(UserRoleEnum::ADMIN->value)
, does it work if you remove the-value
part? (because it does that internally)
Thanks for your quick response. Unfortunately both options do not work. I am ending up in the HasRole.php::242
-Trait. Where the code is
if (is_string($roles)) {
return $guard
? $this->roles->where('guard_name', $guard)->contains('name', $roles)
: $this->roles->contains('name', $roles);
}
and my values are
$roles = "admin";
$guard = null;
$this->roles
is an array with the correct role model. So I didn't understand in the beginning why it didn't work. But my guess is that the contains checks the string
value and probably compares it to the enum which it gets when casting it.