This is part of my Role model:
namespace App;
use App\Traits\Permissions;
use Illuminate\Database\Eloquent\Model;
class Role extends Model
{
use Permissions;
/**
* {@inheritDoc}
*/
protected $casts = [
'permissions' => 'array',
];
}
This is my Permissions trait:
namespace App\Traits;
trait Permissions
{
public function setPermissionsAttribute($permissions)
{
ksort($permissions);
$this->attributes['permissions'] = $permissions;
}
/**
* Adds a permission.
*
* @param string $permission
* @param bool $value
* @return void
*/
public function addPermission($permission, $value = true)
{
if (!array_key_exists($permission, $this->getAttribute('permissions'))) {
$this->setAttribute('permissions', array_merge($this->getAttribute('permissions'), [$permission => $value]));
}
}
}
This will throw the following exception:
QueryException in Connection.php line 769:
Array to string conversion (SQL: update `roles` set `permissions` = 1 where `id` = 46526e77-98b8-4126-aaae-7e109c7ea227)
If I print the $permissions
variable after the ksort
operation it correctly has the permissions array:
array:1 [
"do.this" => true
]
If I remove the setPermissionsAttribute
function it properly serializes the array into json and stores it in the database.
Am I doing something wrong or it's just not possible to use both these features?
$cast
is also sort of a mutator itself. It doesnt make sense to have both any way. You should define another field that is based on the permissions
attribute.
When an attribute is get from the model, the mutateAttribute function is called before the castAttribute. You can check the code behind here
But you can call the castAttribute function in the mutator
public function getPermissionsAttribute($value) {
$p = $this->castAttribute('permissions', $value);
ksort($p);
return $p;
}