簡體   English   中英

如何使用 spatie/laravel-permission 和 webpatser/laravel-uuid 在 Laravel 中正確實現 UUID?

[英]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 作為整數傳輸到此查詢中。現在是342,其他情況類似705293

正如你在這張圖片中看到的,來自 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 dumpautoloadphp 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.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM