[英]How can I correctly implement UUIDs in Laravel with spatie/laravel-permission and webpatser/laravel-uuid?
我有一个 Laravel 5.7 应用程序,它使用 spatie/laravel-permission 和模型的普通 ID。 我想过渡到使用 UUID,并且我已经采取了 webpatser/laravel-uuid 自述文件中提到的步骤。 一切都适用于我自己的模型,例如用户,Model A,Model B 等,关系似乎很好,但我似乎无法使 uuid 与 Spatie 的权限一起工作。
当我想将角色(和相关权限)分配给 object 时,出现以下错误。 当我尝试注册用户并为其分配角色时会发生这种情况。
正如你在这张图片中看到的,来自 Spatie 的 role_id 作为 integer 被传输到这个查询中。现在它是 342,在其他情况下它类似于 705293
我在 /app 文件夹中相应地定义了一个 Uuids.php 特征,并为所有模型添加了以下代码,包括 Permission.php 和 Role.php:
public $incrementing = false;
protected $keyType = 'string';
use Uuids;
protected $casts = [
'id' => 'string',
];
我知道这适用于任何其他 model 和关系,但不适用于 Spatie 的权限,并且似乎 role_id 在内部函数中的转换方式不同(例如 assignRole('') 从 36chars 字符串转换为其他内容。如果我查询角色或权限 我得到正确的字符串 ID。
有什么我可能遗漏的吗,或者有人知道解决这个问题的方法吗?
稍后编辑:这是我对 Spatie 的原始迁移:
<?php
use Illuminate\Support\Facades\Schema;
use Illuminate\Database\Schema\Blueprint;
use Illuminate\Database\Migrations\Migration;
class CreatePermissionTables extends Migration
{
/**
* Run the migrations.
*
* @return void
*/
public function up()
{
$tableNames = config('permission.table_names');
$columnNames = config('permission.column_names');
Schema::create($tableNames['permissions'], function (Blueprint $table) {
$table->uuid('id');
$table->primary('id');
$table->string('name');
$table->string('guard_name');
$table->timestamps();
});
Schema::create($tableNames['roles'], function (Blueprint $table) {
$table->uuid('id');
$table->primary('id');
$table->string('name');
$table->string('guard_name');
$table->timestamps();
});
Schema::create($tableNames['model_has_permissions'], function (Blueprint $table) use ($tableNames, $columnNames) {
$table->uuid('permission_id');
$table->string('model_type');
$table->uuid($columnNames['model_morph_key']);
$table->index([$columnNames['model_morph_key'], 'model_type', ]);
$table->foreign('permission_id')
->references('id')
->on($tableNames['permissions'])
->onDelete('cascade');
$table->primary(
['permission_id', $columnNames['model_morph_key'], 'model_type'],
'model_has_permissions_permission_model_type_primary'
);
});
Schema::create($tableNames['model_has_roles'], function (Blueprint $table) use ($tableNames, $columnNames) {
$table->uuid('role_id');
$table->string('model_type');
$table->uuid($columnNames['model_morph_key']);
$table->index([$columnNames['model_morph_key'], 'model_type', ]);
$table->foreign('role_id')
->references('id')
->on($tableNames['roles'])
->onDelete('cascade');
$table->primary(
['role_id', $columnNames['model_morph_key'], 'model_type'],
'model_has_roles_role_model_type_primary'
);
});
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']);
app('cache')->forget('spatie.permission.cache');
});
}
//Reverse the migrations.
public function down()
{
$tableNames = config('permission.table_names');
Schema::drop($tableNames['role_has_permissions']);
Schema::drop($tableNames['model_has_roles']);
Schema::drop($tableNames['model_has_permissions']);
Schema::drop($tableNames['roles']);
Schema::drop($tableNames['permissions']);
}
}
这是角色和权限如何存储(工作)的示例
权限也是如此。 所以他们的 _id 是正确的。 问题出在 Laravel 或 Spatie 中的某处,它在尝试向 Model 添加角色时向数据库发送另一个值。
不建议更新包中的表。 所以在 app 文件夹中创建一个 trait:
<?php
namespace YourNamespace;
use Illuminate\Support\Str;
trait Uuids
{
/**
* Boot function from Laravel
*/
protected static function boot()
{
parent::boot();
static::creating(function ($model) {
$model->incrementing = false;
$model->{$model->getKeyName()} = Str::uuid()->toString();
});
}
}
创建迁移以更新表结构:
php artisan migrate:make change_primary_key_type_in_roles_table --table=roles
将以下内容放入迁移中:
public function up()
{
Schema::table('roles', function (Blueprint $table) {
$table->uuid('id')->change();
});
}
public function down()
{
Schema::table('roles', function (Blueprint $table) {
$table->increments('id')->change();
});
}
在您的模型中使用 Uuid 特征:
<?php
namespace YourNamespace;
use Illuminate\Database\Eloquent\Model;
class Category extends Model
{
use Uuids;
protected $guarded = [''];
protected $casts = [
'id' => 'string',
];
然后做composer dumpautoload
和php artisan migrate
也面临这个问题。 通过使用以下代码更改 Permission.php 和 Role.php 解决:
public $incrementing = false;
protected $keyType = 'string';
use Uuids;
protected $casts = [
'id' => 'uuid',
];
如果您希望所有角色/权限对象都具有 UUID 而不是 integer,则需要将默认的角色和权限模型扩展到您自己的命名空间中,以便设置一些特定的属性。
namespace App\Models;
use App\Traits\Uuid;
use Illuminate\Database\Eloquent\Model;
use Spatie\Permission\Models\Role as SpatieRole;
class Role extends SpatieRole
{
use Uuid;
protected $primaryKey = 'id';
/**
* The attributes that should be cast to native types.
*
* @var array
*/
protected $casts = [
'id' => 'string',
];
}
然后在 permission.php 中更新配置,更改使用的 model
'permission' => Spatie\Permission\Models\Permission::class,
to
'permission' => App\Models\Permission::class,
'role' => Spatie\Permission\Models\Role::class,
to
'role' => App\Models\Role::class,
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.