在 Laravel 7 中优雅使用 UUID 教程

最近我不得不在 Laravel 7 实现 通用唯一识别码 ( UUIDs ),并遇到一些问题。我希望这帖子可为其他正在做相同事情的人解惑。

使用 UUIDs 的高级理由

A) 它们从你的 统一资源定位符 移除编号的 身份识别号 ,故用户不能看到你的应用已创建多少确定的对象。例如:

https://myapp.com/api/users/5 

对比:

https://myapp.com/api/users/0892b118-856e-4a15-af0c-66a3a4a28eed

B) 它们让 身份识别号 远难于猜测。这有益于安全性,但我们可能应当实现其他技术以防范之。

作为主键实现 UUIDs

如何改变数据库迁移

首先,在数据库迁移中,你要将当前自动递增的 ID 字段替换为 UUIDs 。你还可以遵循以下方法:保留自动递增 ID 并将 UUID 作为表中的附加字段,在用户展示 URL 时使用 (在这种情况下,你将 ID 隐藏到模型中),但这不是我们能在这里做的。 让我们看看假设的 employees 表是什么样子的。

public function up()
 {
 Schema::create('employees',function (Blueprint $table) {
 $table->uuid('id')->primary;
 $table->string('name');
 $table->string('email')->unique();
 $table->string('work_location')->nullable();
 $table->timestamps();
 });
 }

在这里,注意我们用 uuid() 替换了 normal id() ;并使其成为主键。

让我们把它变成一种特质

接下来,我们可以实现 Laravel 生命周期挂钩,以确保在创建此模型的新实例时分配了 UUID。我们可以直接在模型中编写代码,但是如果你要在多个模型中使用 UUID,我建议用 Trait (我在这篇开发文章中学到了这一点,非常感谢 Dev)。trait 基本上允许你创建功能,并通过 use 关键字调用它在多个模型中使用。

要创建新的 Trait,请创建一个 \App\Http\Traits\文件夹 (这仅仅是我的爱好,你也可以将其放到其他位置),并为 Trait 创建一个新文件。我们将调用文件 UsesUuid.php。

这是 trait 的具体代码:

<?php
namespace App\Http\Traits;
use Illuminate\Support\Str;
trait UsesUuid
{
 protected static function bootUsesUuid() {
 static::creating(function ($model) {
 if (! $model->getKey()) {
 $model->{$model->getKeyName()} = (string) Str::uuid();
 }
 });
 }
 public function getIncrementing()
 {
 return false;
 }
 public function getKeyType()
 {
 return 'string';
 }
}

使用 \Illuminate\Support\Str 轻松生成 UUID.。getIncrementing () 方法告诉 Laravel 该模型的主键不会自增 (因为我们设置的是 false),而 getKeyType () 方法告诉 Laravel 该模型的主键是字符串类型。bootUsesUuid () 方法允许我们使用 Laravel 强大的生命周期钩子。你可以 在这来哦藕节更多详细信息。基本上我们的代码已经可以告诉 Laravel,当创建该模型的新实例时,为其设置 UUID 主键!

现在,我们可以使用 use 关键字在模型上轻松实现此特征。

<?php
namespace App;
use Illuminate\Database\Eloquent\Model;
...
class Employee extends Model
{
 ...
 use \App\Http\Traits\UsesUuid;
 ...
}

将 UUID 引用为外键

要将表上的 UUID 引用为外键,只需更改表上外键字段的类型。如下...

Schema::create('another_table',function(Blueprint $table) {
 $table->id();
 $table->unsignedBigInteger('employee_id');
 $table->string('some_field');
 $table->foreign('employee_id')
 ->references('id')
 ->on('shifts')
 ->onDelete('cascade');
 });

... 我们在引用 employee_id 外键时创建了一个无符号大整型的数据类型,对此进行如下修改:

Schema::create('another_table',function(Blueprint $table) {
 $table->id();
 $table->uuid('employee_id');
 $table->string('some_field');
 $table->foreign('employee_id')
 ->references('id')
 ->on('shifts')
 ->onDelete('cascade');
 }); 

那样简单!还有一件事...

UUID 和多态关系

您可能会发现自己通过自己的操作或要引入的包以多态关系引用了该模型。在迁移中,该表可能看起来像这样:

public function up()
{
 Schema::create('some_package_table',function (Blueprint $table) 
 {
 $table->bigIncrements('id');
 $table->morphs('model');
 ...
 }
}

在这里,morphs () 方法将在数据库中创建两个字段,即无符号大整型类型的 model_id 和字符串类型的 model_type。问题在于我们的模型现在使用的是 UUID 而不是递增的整数 ID,因此这会给您带来错误,并显示类似以下内容::

Data truncated for column 'model_id' at row 1

我们现在需要 model_id 字段来支持我们的新 UUID,它的类型是 CHAR (36)。别担心!Laravel 让这件事变得超级简单,你不需要手动做这件事。只需将迁移更改为:

public function up()
{
 Schema::create('some_package_table',function (Blueprint $table) 
 {
 $table->bigIncrements('id');
 $table->uuidMorphs('model');
 ...
 }
} 

更多PHP内容请访问:

腾讯T3-T4标准精品PHP架构师教程目录大全,只要你看完保证薪资上升一个台阶(持续更新)

 

版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 dio@foxmail.com 举报,一经查实,本站将立刻删除。

相关推荐


laravel的dd函数不生效怎么办
看不懂laravel文档咋办
安装laravel框架出现command怎么办
Laravel开发API怎么使用事务
laravel怎么构建复杂查询条件
laravel如何实现防止被下载
为什么laravel比yii火
一些常见的Laravel定时任务不运行的问题
laravel用路由有什么好处
composer无法安装laravel怎么办
laravel现在还用吗
laravel怎么替换主键id
laravel的appurl有什么用
如何修改Laravel的报错输出形式
laravel怎么避免foreach查表
laravel怎样操作数据库
laravel怎么截取字符串
laravel 是国内的吗
laravel怎么设置请求头
浅析Laravel社区Redis组件报错的问题和解决方法