我尝试使用Laravel 8.x和Laravel sanctum 2.14.2来验证我的API和UUID作为我的User模型的主密钥。
我的自定义PersonalAccessToken模型
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迁移模式
...
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
...
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获取令牌时,我会得到以下错误:
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作为用户表中的主键。
Schema::create('users', function (Blueprint $table) {
$table->uuid('uuid')->primary();
...
});更新
我的User模型
...
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");
}
...
}任何帮助都将不胜感激。
发布于 2022-10-07 20:20:11
很抱歉回复晚了。我给出的答案是任何有上述问题的人的答案。问题就在我的UUId Traits里。当我们想要创造我们自己的特质时,我们应该像拉勒维尔所建议的那样使用boot magic method。
解决方案:
在正确的代码中使用App\Traits\HasUUID
<?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模型中。
...
use App\Traits\HasUUID;
...
class User extends Authenticatable
{
use HasUUID;
...
}不需要自定义Sanctum's Model。“非常感谢”侯赛因,“达尔曼”
发布于 2022-03-20 19:58:54
您有什么特别的理由要创建自定义PersonalAccessToken模型吗?
如果只需要UUID作为User模型的主键,则无需创建自定义PersonalAccessToken模型就可以实现它。
您的personal_access_tokens迁移模式似乎很好。
我认为错误的原因是我使用uuid作为用户表中的主键。 架构:创建(‘用户’,函数(Blueprint $table) { $table->uuid('uuid')->primary();…};
这可能就是问题所在。尝试将列名更改为uuid中的仅id,并查看它是否有效。
$table->uuid('id')->primary();如果必须将列名用作主键的uuid,则尝试将以下内容添加到User模型中
protected $primaryKey='uuid'默认情况下,雄辩者假定主键列的名称为'id'。这将让雄辩者知道如何寻找'uuid'作为用户模型的主键列。
另外,由于您没有对主键使用默认的整数数据类型,所以请确保您的User模型中有以下内容
public $incrementing=false
protected $keyType='string'您可以参考主键的Laravel文档
https://stackoverflow.com/questions/71546856
复制相似问题