Search code examples
phpmysqllaravellaravel-permission

Illegal offset type when assigning Permission into Role in spatie/laravel-permission using UUID


I have implemented laravel-permission to custom my Model using UUID primary key. Then I created a seeder:

$viewemployee = Permission::create(['id' => Str::uuid(), 'name' => 'view employee']);
$A = Role::create(['id' => Str::uuid(), 'name' => 'A']);

But, when I'm trying to assign the permission to the role using:

$A->givePermissionTo($viewemployee);

It shows error like this when I run the seed

ErrorException Illegal offset type at vendor/laravel/framework/src/Illuminate/Database/Eloquent/Relations/Concerns/InteractsWithPivot>Table.php:139

Then, I tried another method to assign:

$viewemployee->assignRole($A);

But, it shows another error:

Illuminate\Database\QueryException SQLSTATE[23000]: Integrity constraint violation: 1452 Cannot add or update a child row: a foreign key constraint fails (db.role_has_permissions, CONSTRAINT role_has_permissions_role_id_foreign FOREIGN KEY (role_id) REFERENCES roles (id) ON DELETE CASCADE) (SQL: insert into role_has_permissions (permission_id, role_id) values (8f98272b-cbc3-459b-ab23-fc8fa86dd199, 0))

I have followed the documentation about UUID and Extending correctly, yet I still can't figure it out what I miss so that I can't run my seed.

role and permission data are successfully inserted, it seems like have a trouble when trying to insert to role_has_permissions pivot table.

Here's my migration for permissions, roles and role_has_permissions tables:

Schema::create($tableNames['permissions'], function (Blueprint $table) {
      $table->uuid('id');
      $table->string('name');
      $table->string('guard_name');
      $table->timestamps();

      $table->primary('id');
});

Schema::create($tableNames['roles'], function (Blueprint $table) {
     $table->uuid('id');
     $table->string('name');
     $table->string('guard_name');
     $table->timestamps();

     $table->primary('id');
});

Schema::create($tableNames['role_has_permissions'], function (Blueprint $table) use ($tableNames) {
    $table->uuid('permission_id');
    $table->uuid('role_id');

    $table->foreign('permission_id')
        ->references('id')
        ->on($tableNames['permissions'])
        ->onDelete('cascade');

    $table->foreign('role_id')
        ->references('id')
        ->on($tableNames['roles'])
        ->onDelete('cascade');

    $table->primary(['permission_id', 'role_id'], 'role_has_permissions_permission_id_role_id_primary');
});

Solution

  • You need to cast Str::uuid() to a string (string)Str::uuid()

    $viewemployee = Permission::create(['id' => (string)Str::uuid(), 'name' => 'view employee']);
    

    Otherwise ID's Permission will be a UUID object instead of a UUID string.