首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >用户模型中带有uuid列的Laravel没有保存tokenable_id

问用户模型中带有uuid列的Laravel没有保存tokenable_id
EN

Stack Overflow用户
提问于 2022-03-20 12:44:06
回答 2查看 2.1K关注 0票数 2

我尝试使用Laravel 8.x和Laravel sanctum 2.14.2来验证我的API和UUID作为我的User模型的主密钥。

我的自定义PersonalAccessToken模型

代码语言:javascript
复制
use Illuminate\Database\Eloquent\Factories\HasFactory;
use Laravel\Sanctum\PersonalAccessToken as SanctumPersonalAccessToken;

class PersonalAccessToken extends SanctumPersonalAccessToken
{
    use HasFactory;

    protected $table = 'personal_access_tokens';

    public function tokenable()
    {
        return $this->morphTo('tokenable', "tokenable_type", "tokenable_id", "uuid");
    }
}

我的personal_access_tokens迁移模式

代码语言:javascript
复制
...
    public function up()
    {
        Schema::dropIfExists('personal_access_tokens');

        Schema::create('personal_access_tokens', function (Blueprint $table) {
            $table->id();
            $table->uuidMorphs('tokenable');
            $table->string('name');
            $table->string('token', 64)->unique();
            $table->text('abilities')->nullable();
            $table->timestamp('last_used_at')->nullable();
            $table->timestamps();
        });
    }
...

我的AppServiceProvider

代码语言:javascript
复制
...
use App\Models\PersonalAccessToken;
use Illuminate\Support\Facades\URL;
use Illuminate\Support\ServiceProvider;
use Laravel\Sanctum\Sanctum;

class AppServiceProvider extends ServiceProvider
{
    /**
     * Register any application services.
     *
     * @return void
     */
    public function register()
    {
        Sanctum::ignoreMigrations();
    }

    /**
     * Bootstrap any application services.
     *
     * @return void
     */
    public function boot()
    {
        if($this->app->environment('production')) {
            URL::forceScheme('https');
        }

        Sanctum::usePersonalAccessTokenModel(PersonalAccessToken::class);
    }
}

当我尝试用$user->createToken($user->email)->plainTextToken获取令牌时,我会得到以下错误:

代码语言:javascript
复制
SQLSTATE[23000]: Integrity constraint violation: 1048 Column 'tokenable_id' cannot be null (SQL: insert into `personal_access_tokens` (`name`, `token`, `abilities`, `tokenable_id`, `tokenable_type`, `updated_at`, `created_at`) values (admin@gmail.com, 85dbe44c32a999a01f4a97d9c9eab0710125a6ac5f861ab546a5822f61015b23, [\"*\"], ?, App\\Models\\User, 2022-03-20 19:16:43, 2022-03-20 19:16:43))

我认为导致此错误的原因是我使用uuid作为用户表中的主键。

代码语言:javascript
复制
Schema::create('users', function (Blueprint $table) {
      $table->uuid('uuid')->primary();
      ...
});

更新

我的User模型

代码语言:javascript
复制
...
class User extends Authenticatable
{
    use HasUUID;
    use HasApiTokens;
    use HasFactory;
    use Notifiable;
    use HasRoles;

    ...

    public function tokens()
    {
        return $this->morphMany(Sanctum::$personalAccessTokenModel, 'tokenable', "tokenable_type", "tokenable_id");
    }
    
    ...
}

任何帮助都将不胜感激。

EN

回答 2

Stack Overflow用户

回答已采纳

发布于 2022-10-07 20:20:11

很抱歉回复晚了。我给出的答案是任何有上述问题的人的答案。问题就在我的UUId Traits里。当我们想要创造我们自己的特质时,我们应该像拉勒维尔所建议的那样使用boot magic method。

解决方案:

在正确的代码中使用App\Traits\HasUUID

代码语言:javascript
复制
<?php

namespace App\Traits;

use Illuminate\Database\Eloquent\Model;
use Illuminate\Support\Str;

trait HasUUID
{
    /**
     * Boot functions from Laravel.
     */
    // protected static function boot() <- This line is INCORRECT
    protected static function bootHasUUID()
    {
        static::creating(function (Model $model) {
            $model->primaryKey = 'uuid';
            $model->keyType = 'string'; // In Laravel 6.0+ make sure to also set $keyType
            $model->incrementing = false;

            if (empty($model->{$model->getKeyName()})) {
                $model->{$model->getKeyName()} = Str::uuid()->toString();
            }
        });
    }

    /**
     * Get the value indicating whether the IDs are incrementing.
     *
     * @return bool
     */
    public function getIncrementing()
    {
        return false;
    }

    /**
     * Get the auto-incrementing key type.
     *
     * @return string
     */
    public function getKeyType()
    {
        return 'string';
    }
}

最后,将App\Traits\HasUUID添加到User模型中。

代码语言:javascript
复制
...
use App\Traits\HasUUID;
...
class User extends Authenticatable
{
    use HasUUID;
    ...
}

不需要自定义Sanctum's Model。“非常感谢”侯赛因,“达尔曼”

票数 0
EN

Stack Overflow用户

发布于 2022-03-20 19:58:54

您有什么特别的理由要创建自定义PersonalAccessToken模型吗?

如果只需要UUID作为User模型的主键,则无需创建自定义PersonalAccessToken模型就可以实现它。

您的personal_access_tokens迁移模式似乎很好。

我认为错误的原因是我使用uuid作为用户表中的主键。 架构:创建(‘用户’,函数(Blueprint $table) { $table->uuid('uuid')->primary();…};

这可能就是问题所在。尝试将列名更改为uuid中的仅id,并查看它是否有效。

代码语言:javascript
复制
$table->uuid('id')->primary();

如果必须将列名用作主键的uuid,则尝试将以下内容添加到User模型中

代码语言:javascript
复制
protected $primaryKey='uuid'

默认情况下,雄辩者假定主键列的名称为'id'。这将让雄辩者知道如何寻找'uuid'作为用户模型的主键列。

另外,由于您没有对主键使用默认的整数数据类型,所以请确保您的User模型中有以下内容

代码语言:javascript
复制
public $incrementing=false
protected $keyType='string'

您可以参考主键的Laravel文档

票数 2
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/71546856

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档