В прошлой статье мы разобрались как в [Laravel работать с UUID](https://laravel.demiart.ru/laravel-uuid/). Но он не решает всех проблем распределенных систем. Один из новых подходов к генерации уникальных идентификаторов это **ULID — Universally Unique Lexicographically Sortable Identifier** (универсальный уникальный лексографически сортируемый идентификатор). ##Сравнение UUID и ULID Во многих случаях использование UUID неоптимально: * Это не самый эффективный способ кодирования 128-битной случайности * UUID v1/v2 непрактичен во многих средах, так как требует доступа к уникальному стабильному MAC-адресу * UUID v3/v5 требует уникального начального числа и генерирует случайно распределенные идентификаторы, которые могут вызвать фрагментацию во многих структурах данных * UUID v4 не предоставляет никакой другой информации, кроме случайности, которая может вызвать фрагментацию во многих структурах данных Вместо этого ULID предлагает: * 128-битная совместимость с UUID * 1.21e+24 уникальных ключей в миллисекунду * Лексикографическая сортировка (т.е. в алфавитном порядке) * Канонически кодируется как 26-символьная строка, в отличие от 36-символьного UUID * Использует Crockford Base32 для лучшей эффективности и читаемости (5 бит на символ). Исключены буквы I, L, O, чтобы не путать с цифрами. И буква U, чтобы случайно не сгенерировались непристойность * Регистронезависимый * Без специальных символов (безопасный URL) * Точность метки времени до миллисекунды * Да просто выглядит эстетичнее, чем UUID :) Более подробно можно узнать в [спецификации ULID](https://github.com/ulid/spec) Пример ULID: ``` ulid(); // 01d85pp1982gf6ktvfhq7w78fb 01d85pp198 2gf6ktvfhq7w78fb Timestamp Randomness 48bits 80bits ``` ##Когда нужен ULID в качестве первичного ключа? В распределенных системах, когда нужна уверенность, что у идентификаторов не будет коллизий. В высоконагруженной системы, когда автоинкрементный ключ не вариант. Когда нужна репликация без геморроя (в отличии от int). Когда не хотите показывать пользователю, что получаете информацию об идентификаторе (например: example.com/user/3) ##Использование ULID в Laravel Ставим пакет ``` composer require rorecek/laravel-ulid:^2.0.0 ``` Создаём модель ``` php artisan make:model Product -mcr ``` Исправляем в миграции модели строку $table->increments(‘id’); на $table->char(‘id’, 26)->primary(); Если связанная модель использует ULID, то тип колонки должен это отображать ``` Schema::create('products', function (Blueprint $table) { $table->char('id', 26)->primary(); .... // связанная модель $table->char('category_id', 26); $table->foreign('category_id')->references('id')->on('categories'); .... $table->timestamps(); }); ``` В модели укажите использование трейта HasUlid и выставьте флаг incrementing на false. ``` use Illuminate\Database\Eloquent\Model; use Rorecek\Ulid\HasUlid; class Product extends Model { use HasUlid; .... /** * Indicates if the IDs are auto-incrementing. * * @var bool */ public $incrementing = false; .... } ``` Теперь, когда вы создаете новый экземпляр модели, ULID генерируется автоматически. ``` $item = Product::create(); echo $item->id; // 01d85pp1982gf6ktvfhq7w78fb ```