Использование UUID в качестве первичного ключа с Laravel 5

Я пытаюсь создать таблицы, которые будут иметь первичный ключ, который является UUID, определяемым как binary(16) а не по умолчанию автоматически увеличивающимся id полем.

Мне удалось создать миграции с использованием необработанных 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;"); 

Однако у меня проблемы с работой модели. Я следил за учебником, доступным здесь . Я определил свою модель следующим образом:

 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(); } } 

где Uuid является псевдонимом Webpatser\Uuid .

Одна из проблем, с UuidModel я сталкиваюсь, – это не могу получить UuidModel от Eloquent как объяснено в учебнике. На самом деле я не вижу класс Eloquent . Вместо этого я получаю от Model . Я предполагаю, что учебник был написан в Laravel 4.

Я был бы признателен за помощь в реализации таблиц с UUID в качестве основных ключей в Laravel 5.

EDIT 1: Итак, если я определяю свой класс следующим образом:

 use Illuminate\Database\Eloquent class UuidModel extends Eloquent { ... } 

Я получаю следующую ошибку:

 PHP Fatal error: Class 'Illuminate\Database\Eloquent' not found in /home/vagrant/transactly/app/UuidModel.php on line 8 

Если я удалю use Illuminate\Database\Eloquent строки use Illuminate\Database\Eloquent , я получаю следующую ошибку:

 PHP Fatal error: Class 'App\Eloquent' not found in /home/vagrant/transactly/app/UuidModel.php on line 8 

Изменить 2: Я обнаружил, что событие static::creating UuidModel никогда не вызывается, когда UuidModel экземпляры UuidModel .

Я попытался настроить creating прослушиватель событий в AppServiceProvider но это тоже не называется. Интересно, что событие 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(){} } 

Итак, я получил то, что работает как шарм (не тестировалось модульное тестирование):

  1. class UuidModel extends Eloquent – это более старая (Laravel 4) конструкция. Мы используем class UuidModel extends Model в Laravel 5
  2. Решением было перемещение

     UuidModel::creating(function ($model) { echo "Creating Uuid Model...\n"; $model->{$model->getKeyName()} = (string)$model->generateNewId(); }); 

    из AppServiceProvider::boot() в EventServiceProvider::boot() . Никаких других изменений не требовалось. Все работало, как ожидалось.

Я до сих пор не знаю, почему (2) работает в EventServiceProvider а не в AppServiceProvider как объясняется в официальных документах . Но, судя по имени, возможно, так оно и должно быть.

Как насчет этой идеи для хранения 36chr UUID как двоичного (16):

ИМО есть преимущество в том, что Laravel не генерирует UUID . А именно, если новые записи (в будущем в будущем) будут вставлены в базу данных извне приложения, поле UUID будет правильно заполнено.

Мое предложение: Создайте триггер значения по умолчанию UUID, используя миграцию

(этот триггер заставляет сервер 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`'); } } 

Наконец, если вы хотите получить удобочитаемую версию вашего UUID, просто выполните следующие действия:

 SELECT HEX(UUID) FROM customers; 

В любом случае, надеюсь, что это кому-то поможет 🙂

Это быстрое решение без использования событий.

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 } } ?> 

Пример модели Car.php

 <?php namespace App; class Car extends UuidModel { } 

также попробуйте использовать этот пакет, который автоматически сгенерирует и присвоит поле UUID в вашей модели, также может отображать и обновлять ключ UUID.

https://github.com/EmadAdly/laravel-uuid