[英]Using a UUID as primary key with Laravel 5
I'm trying to create tables that will have a primary key which is a UUID defined as binary(16)
instead of the default auto-incrementing id
field. 我正在尝试创建具有主键的表,该主键是定义为
binary(16)
的UUID,而不是默认的自动递增id
字段。
I've managed to create migrations using raw SQL statements though DB::statement
like so: 我设法使用原始SQL语句创建迁移虽然
DB::statement
如下:
DB::statement("CREATE TABLE `binary_primary_keys` (
`uuid` binary(16) NOT NULL DEFAULT '\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0',
`created_at` timestamp NOT NULL DEFAULT '0000-00-00 00:00:00',
`updated_at` timestamp NOT NULL DEFAULT '0000-00-00 00:00:00',
PRIMARY KEY (`uuid`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8 COLLATE=utf8_unicode_ci;");
However, I have trouble getting the model working. 但是,我无法让模型正常工作。 I've followed the tutorial available here .
我按照这里提供的教程进行了操作 。 I've defined my model like so:
我已经定义了我的模型:
class UuidModel extends Model
{
public $incrementing = false;
public $primaryKey = 'uuid';
/**
* The "booting" method of the model.
*
* @return void
*/
protected static function boot()
{
parent::boot();
/**
* Attach to the 'creating' Model Event to provide a UUID
* for the `id` field (provided by $model->getKeyName())
*/
static::creating(function ($model) {
$model->{$model->getKeyName()} = (string)$model->generateNewId();
echo($model->{$model->getKeyName()});
});
}
/**
* Get a new version 4 (random) UUID.
*/
public function generateNewId()
{
return Uuid::generate();
}
}
where Uuid
is an alias to Webpatser\\Uuid
. 其中
Uuid
是Webpatser\\Uuid
的别名。
One problem, I'm having is I cannot derive UuidModel
from Eloquent
as explained in the tutorial. 一个问题,我有是我不能获得
UuidModel
从Eloquent
作为教程解释。 In fact I don't see an Eloquent
class. 事实上,我没有看到一个
Eloquent
课程。 I'm deriving from Model
instead. 我是从
Model
衍生出来的。 I am guessing the tutorial was written in Laravel 4. 我猜这个教程是用Laravel 4编写的。
I would appreciate help in implementing tables with UUIDs as primary keys in Laravel 5. 我很感激帮助实现将UUID作为Laravel 5主键的表。
EDIT 1: So, if I define my class like so: 编辑1:所以,如果我这样定义我的类:
use Illuminate\Database\Eloquent
class UuidModel extends Eloquent { ... }
I get the following error: 我收到以下错误:
PHP Fatal error: Class 'Illuminate\Database\Eloquent' not found in /home/vagrant/transactly/app/UuidModel.php on line 8
If I remove the use Illuminate\\Database\\Eloquent
line, I get the following error: 如果我删除
use Illuminate\\Database\\Eloquent
行,我会收到以下错误:
PHP Fatal error: Class 'App\Eloquent' not found in /home/vagrant/transactly/app/UuidModel.php on line 8
Edit 2: I have discovered that the static::creating
event is never called for when instances of UuidModel
are created. 编辑2:我发现在
static::creating
UuidModel
实例时永远不会调用static::creating
事件。
I tried setting up the creating
event listener in AppServiceProvider
but that's not being called as well. 我尝试在
AppServiceProvider
设置creating
事件监听器,但是也没有调用它。 Interestingly, the creating
event is not called for a regular Laravel generated model User
either. 有趣的是,
creating
事件不是为常规Laravel生成的模型User
调用的。
class AppServiceProvider extends ServiceProvider
{
/**
* Bootstrap any application services.
*
* @return void
*/
public function boot()
{
/**
* Attach to the 'creating' Model Event to provide a UUID
* for the `id` field (provided by $model->getKeyName())
*/
echo "Booting...\n";
UuidModel::creating(function ($model) {
echo "Creating Uuid Model...\n";
$model->{$model->getKeyName()} = (string)$model->generateNewId();
});
User::creating(function($user){
echo "Creating User Model...";
$user->name = 'Forced Name in boot()';
});
}
public function register(){}
}
So, I got the thing working like a charm (not tested unit testing): 所以,我得到的东西就像一个魅力(没有经过测试的单元测试):
class UuidModel extends Eloquent
is an older (Laravel 4) construct. class UuidModel extends Eloquent
是一个较旧的(Laravel 4)构造。 We use class UuidModel extends Model
in Laravel 5 class UuidModel extends Model
The solution was to move the 解决方案是移动
UuidModel::creating(function ($model) { echo "Creating Uuid Model...\\n"; $model->{$model->getKeyName()} = (string)$model->generateNewId(); });
from AppServiceProvider::boot()
to EventServiceProvider::boot()
. 从
AppServiceProvider::boot()
到EventServiceProvider::boot()
。 No other changes were required. 无需其他更改。 Everything worked as expected.
一切都按预期工作。
I still don't know why (2) works in EventServiceProvider
and not in AppServiceProvider
as explained in the official docs . 我仍然不知道为什么(2)在
EventServiceProvider
工作,而不是在官方文档中解释的AppServiceProvider
中。 But judging from the name, that's perhaps the way it was meant to be. 但从名称来看,这可能是它的意图。
How about this idea for storing a 36chr UUID as Binary(16) : 将36chr UUID存储为二进制(16)的想法怎么样:
IMO there is an advantage in not having Laravel generating the UUID . IMO 在没有Laravel生成UUID方面有一个优势 。 Namely, if new records (some day in the future) get inserted into the database from outside the application the UUID field is properly populated.
也就是说,如果新记录(将来的某一天)从应用程序外部插入到数据库中,则可以正确填充UUID字段。
(this trigger makes the DataBase server do the work to generate the UUID each time a new customer is inserted) (此触发器使DataBase服务器完成每次插入新客户时生成UUID的工作)
<?php namespace MegaBank\HighInterestLoans\Updates;
use Illuminate\Database\Schema\Blueprint;
use Illuminate\Database\Migrations\Migration;
class MigrationTriggerForCustomers extends Migration
{
public function up()
{
DB::unprepared('CREATE TRIGGER before_insert_customers
BEFORE INSERT ON
`megabank_highinterestloans_customers`
FOR EACH ROW
SET new.uuid = UNHEX(REPLACE(UUID(), "-","");');
}
public function down()
{
DB::unprepared('DROP TRIGGER `before_insert_customers`');
}
}
Finally, if you want to get a human-readable version of your UUID just do the following: 最后,如果您想获得UUID的人类可读版本,请执行以下操作:
SELECT HEX(UUID) FROM customers;
Anyway, hope this helps someone :-) 无论如何,希望这有助于某人:-)
This is a quick solution without using events. 这是一种不使用事件的快速解决方案。
UUidModel.php UUidModel.php
<?php namespace App;
use \Illuminate\Database\Eloquent\Model;
use \Illuminate\Database\Eloquent\Builder;
class UuidModel extends Model
{
/**
* Insert the given attributes and set the ID on the model.
*
* @param \Illuminate\Database\Eloquent\Builder $query
* @param array $attributes
* @return void
*/
protected function insertAndSetId(Builder $query, $attributes)
{
$keyName = $this->getKeyName();
$id = $attributes[$keyName] = $this->generateNewId();
$query->insert($attributes);
$this->setAttribute($keyName, $id);
}
/**
* Get a new version 4 (random) UUID.
*/
public function generateNewId()
{
return 'uuid!!' ;// just for test
}
}
?>
Model Example Car.php 模型示例Car.php
<?php namespace App;
class Car extends UuidModel {
}
also try use this package will automatically generate and assign UUID field in your model, also can show and update by UUIDs key. 也尝试使用此包将自动生成并在您的模型中分配UUID字段,也可以通过UUIDs键显示和更新。
https://github.com/EmadAdly/laravel-uuid https://github.com/EmadAdly/laravel-uuid
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.