Версия для печати | оригинал записи

Laravel и UUID

ash — Log-ово Хозяина

10 апреля 2019 19:10
Laravel и UUID
[attachid=599660]

Что такое UUID?

UUID это универсальный уникальный идентификатор. 16-байтный (128-битный) номер, используемый для уникальной идентификации какого-либо объекта без общего центра координации. То есть мы самостоятельно генерируем UUID и уверены, что полученный идентификатор уникален. Общее количество уникальных ключей UUID составляет 2128 = 25616 или около 3,4 x 1038. Генерируя 1 триллион ключей каждую наносекунду, перебрать все возможные значения удастся лишь за 10 миллиардов лет. В шестнадцатеричной системе счисления UUID выглядит как:
9675e665-1923-4c6f-97c0-259b191fab24

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

[CUT]
Подготавливаем миграцию

Первым шагом использования UUID в вашей базе данных это настройка столбца идентификатора. По умолчанию в каждой миграция Laravel автоматически создается стобец $table->primary('id');.

Использовать UUIDs так же просто, как обновить миграцию. Добавляем метод ->uuid(), доступный прямо из «коробки». Например миграция для сущности Post:
Цитирую (PHP)
Schema::create('posts', function (Blueprint $table) {
    $table
->uuid('id')->primary();
    $table
->string('title');
    $table
->text('body');
    $table
->timestamps();
});

Обратите внимание на строку: $table->uuid('id')->primary();. Мы используем метод uuid() вместо обычного increments().


Создание UUID

Если вы запустите php artisan migrate и попытаетесь создать новую запись, через фабрику или вручную, то получите ошибку, утверждающую, что столбец id не может быть null.

При использовании метода primary() в миграциях Laravel понимает, что это автоинкрементный столбец, и создает его таким. Но, поскольку мы перешли на использование UUID, нам нужно создавать ID самостоятельно.


Используем события модели Eloquent

Раз мы работает с Laravel, то скорей всего используем и Eloquent для взаимодействия с базой данных.

Eloquent имеет так называемую Событийная модель (Model Events). В общей сложности он запускает 11 событий в разных сценариях:
Цитирую (HTML)
    retrieved
    creating
    created
    updating
    updated
    saving
    saved
    deleting
    deleted
    restoring
    restored

Если вы хотите узнать о Событиях больше, то ознакомьтесь с документацией.

Вернемся к созданию UUID. Давайте посмотрим, как может выглядеть ваша модель Post:
Цитирую (PHP)
class Post extends Model
{
    protected $guarded = [];

    protected static function boot()
    {
        parent
::boot();

        static::creating(function ($post) {
            $post
->{$post->getKeyName()} = (string) Str::uuid();
        });
    }

    public function getIncrementing()
    {
        return false;
    }

    public function getKeyType()
    {
        return 'string';
    }
}

Модель имеет 3 метода. В методе boot мы можем подключиться к нашей модели и прослушивать любые события Eloquent. Метод getIncrementing используется Eloquent, если идентификаторы в таблице инкрементны. Помните, мы используем UUID, поэтому устанавливаем false на автоинкремент. А метод getKeyType просто указывает, что идентификаторы в таблице должны храниться в виде строк.

В нашем методе boot мы ожидаем события creating. Оно запускается непосредственно перед тем, как запись сохраняется в базе данных. Мы подключаемся к этому событию и используем метод uuid(), предоставленный классом Str в Laravel.

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

Обычно я делаю отдельный трейт (trait) под названием UsesUuid, где я храню логику, описанную выше. Это позволяет не повторять код для каждой модели, где нужно использовать UUID:
Цитирую (PHP)
<?php

namespace App\Models\Concerns;

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';
    }
}

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

Теперь в любой модели, вы можете просто использовать трейт UsesUuid следующим образом:
Цитирую (PHP)
class Post extends Model
{
  use App\Models\Concerns\UsesUuid;

  protected $guarded = [];
}

Вот и все. Всего за несколько простых шагов вы получили UUID для Laravel.


Автор: Wilbur Powery
Перевод: Demiurge Ash[/CUT]

Комменты: 0


Demiart © 2019