首页 > 解决方案 > 如何使用 spatie/laravel-permission 和 webpatser/laravel-uuid 在 Laravel 中正确实现 UUID?

问题描述

我有一个 Laravel 5.7 应用程序,使用 spatie/laravel-permission 和模型的普通 ID。我想过渡到使用 UUID,并且我已经采取了 webpatser/laravel-uuid 自述文件中提到的步骤。一切都适用于我自己的模型,例如用户、模型 A、模型 B 等,并且关系似乎很好,但我似乎无法使用 Spatie 的权限使 uuid 工作。

当我想为对象分配角色(和相关权限)时,我收到以下错误。当我尝试注册用户并为他分配角色时会发生这种情况。

正如您在此图中看到的,来自 Spatie 的 role_id 作为整数传输到此查询中。 现在是 342,其他情况类似于 705293

正如您在此图中看到的,来自 Spatie 的 role_id 作为整数传输到此查询中。现在是 342,其他情况类似于 705293

我已经在我的 /app 文件夹中相应地定义了 Uuids.php 特征,并为所有模型(包括 Permission.php 和 Role.php)添加了以下代码:

public $incrementing = false;
protected $keyType = 'string';

use Uuids;

protected $casts = [
    'id' => 'string',
];

我知道这适用于任何其他模型和关系,但不适用于 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 中的某个地方,当尝试将角色添加到模型时,它会向数据库发送另一个值。

标签: phplaravelpermissionsuuidlaravel-permission

解决方案


不建议更新包中的表格。所以在 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 dumpautoloadphp artisan migrate


推荐阅读