Search code examples
phplaravellaravel-9laravel-permission

Spatie role plugin for Laravel + seed users with roles, doesn't assignRole


At laravel 9 I tried to seed users with role

Spatie just procced everything without error, but in database relations between role and users didn't appear in model in table "model_has_role"

I created role like

$roleName = 'MyRole';
$guardName = 'myGuard';

$roleObj = Role::create(['guard_name' => $guardName, 'name' => $roleName]);

Then created users like

$user = new User($userDatas);

I collected all datas from model what should be filled by

$arrayWithUsersData = [];

foreach($users as $user)
{
   if($users !== NULL)
   {
      $arrayWithUsersData[] = $user->getAttributes();
   }
}

After this i tried to insert all users at once into database so i used

DB::table('users')->insert($arrayWithUsersData);

and at end i tried in foreach $users any possible way to assign role like:

$user->assignRole($roleName);
$user->assignRole($roleName, $guardName);
$user->assignRole([$roleName, $guardName]);
$user->assignRole($myRole);
$user->assignRole($myRole, $guardName);
$user->assignRole([$myRole, $guardName]);
$user->syncRoles($myRole);
$user->syncRoles($myRole, $guardName);
$user->syncRoles([$myRole, $guardName]);

But nothing gived any error but still didnt create relation


Solution

  • Problem was that spatie in assignRole and syncRole valid if model exists

    I mean laravel models have property "exists"

    theres some code from assignRole function in vendor\spatie\laravel-permission\src\Traits\HasRoles.php

    • and syncRoles is wrapper for assignRole

        $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) {
                    if ($model->getKey() != $object->getKey()) {
                        return;
                    }
                    $model->roles()->sync($roles, false);
                    $model->load('roles');
                }
            );
        }
      

    So DB::table('users')->insert($arrayWithUsersData); don't change param "exists" in model since it works on raw data

    So i had to switch to create users 1 by 1 and save them like

    $user = new User($userData);
    $user->save();
    

    And now spatie create relations as it should.