enbermudas
enbermudas

Reputation: 1615

Spatie laravel/permission - Modifying table and methods

I'm working with Laravel 5.6 and Spatie laravel-permission and I want to modify the model_has_roles so it can have an extra field named code.

Now, i did that thing by modifying the migrations the library provides via the next command:

php artisan vendor:publish --provider="Spatie\Permission\PermissionServiceProvider" --tag="migrations"

This library provides a useful command:

$user->assignRole($role);

That lets me assign a role to an user within a single line of code. My problem is that, using this command will throw an error because i can't leave the code field empty. Either way, i can't do something like this:

$user->assignRole($role, ['code' => '0001']);

Because it will say that 0001 is not a role. Basically, it asumes that i'm trying to assign TWO different roles to the user: $role and 0001 while actually i'm trying to assign a single role: $role with an extra parameter for the table model_has_roles.

Is there a way to archieve such a thing? I thought that maybe i could modify the logic behind the assignRole method but i don't know how to extend/edit the library methods.

Upvotes: 0

Views: 4063

Answers (1)

Pankaj
Pankaj

Reputation: 719

I see you have already added the column in the migration so now you need to make the changes in the assignRole method.

Spatie permission package works by adding the HasRoles trait in the User model class.

This is the full path of the trait-

use Spatie\Permission\Traits\HasRoles;

To achieve what you desire with the assignRole method, you can simply copy the content from HasRoles trait and then create your own trait from this code. You can see the method in this trait-

    public function assignRole(...$roles)
    {
        $roles = collect($roles)
            ->flatten()
            ->map(function ($role) {
                if (empty($role)) {
                    return false;
                }

                return $this->getStoredRole($role);
            })
            ->filter(function ($role) {
                return $role instanceof Role;
            })
            ->each(function ($role) {
                $this->ensureModelSharesGuard($role);
            })
            ->map->id
            ->all();

        $model = $this->getModel();

        if ($model->exists) {
            $this->roles()->sync($roles, false);
            $model->load('roles');
        } else {
            $class = \get_class($model);

            $class::saved(
                function ($object) use ($roles, $model) {
                    static $modelLastFiredOn;
                    if ($modelLastFiredOn !== null && $modelLastFiredOn === $model) {
                        return;
                    }
                    $object->roles()->sync($roles, false);
                    $object->load('roles');
                    $modelLastFiredOn = $object;
                });
        }

        $this->forgetCachedPermissions();

        return $this;
    }

Make your desired changes in this method and use your custom trait rather than using the spatie's HasRole trait.

Alternatively, you can also override the method from HasRoles trait in your class which is an easier and preferred way.

Upvotes: 1

Related Questions