同时使用Laravel演员和变异器

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;
}