Компонент UID
Дата оновлення перекладу 2024-05-07
Компонент UID
Компонент UID надає утиліти для роботи з унікальними ідентифиіаторами (UIDs), на кшталт UUID и ULID.
Установка
1
$ composer require symfony/uid
Note
Якщо ви встановлюєте цей компонент поза додатком Symfony, вам потрібно підключити
файл vendor/autoload.php
у вашому коді для включення механізму автозавантаження
класів, наданих Composer. Детальніше можна прочитати у цій статті.
UUID
UUID (універсально унікальні ідентифікатори) - це одні з найпопулярніших UID
в індустрії ПЗ. UUID - це 128-бітні числа, зазвичай представлені у вигляді 5 груп
шістнадцяткових символів: xxxxxxxx-xxxx-Mxxx-Nxxx-xxxxxxxxxxxx
(знак M
- UUID
версія, а знак N
- UUID-варіант).
Створення UUID
Використайте іменовані конструктри класу Uuid
або будь-яких інших конкретних класів,
щоб створити кожний тип UUID:
UUID v1 (заснований на часі)
Генерує UUID за допомогою мітки часу і MAC-адреси вашого пристрою (читайте специфікацію UUIDv1). Обидва значення отримуються автоматично, тому вам не потрібно передавати жодного аргументу конструктора:
1 2 3 4
use Symfony\Component\Uid\Uuid;
// $uuid є екземпляром Symfony\Component\Uid\UuidV1
$uuid = Uuid::v1();
Tip
Рекомендується використовувати UUIDv7 замість UUIDv1, оскільки він забезпечує кращу ентропію.
UUID v2 (безпека DCE)
Подібно до UUIDv1, але з дуже високою ймовірністю зіткнення ідентифікаторів (читайте специфікацію UUIDv2). Це частина механізму аутентифікації DCE (Distributed Computing Environment - розподілене обчислювальне середовище) і UUID включає в себе POSIX UID (ідентифікатор користувача/групи) користувача, який його згенерував. Цей варіант UUID не реалізовано компонентом Uid.
UUID v3 (заснований на імені, MD5)
Створює UUID з імен, які належать і є унікальними у заданому просторі імен
(читайте специфікацію UUIDv3).
Цей варіант корисний для створення детермінованих UUID з довільних рядків.
Він працює шляхом заповнення змісту UUID хешем md5
конкатенації
простору імен та імені:
1 2 3 4 5 6 7 8 9 10
use Symfony\Component\Uid\Uuid;
// ви можете використати будь-яке з попередньо визначених просторів імен...
$namespace = Uuid::fromString(Uuid::NAMESPACE_OID);
// ...або використати довільний простір імен:
// $namespace = Uuid::v4();
// $name може бути будь-яким довільним рядком
// $uuid is an instance of Symfony\Component\Uid\UuidV3
$uuid = Uuid::v3($namespace, $name);
Ось простори імен за замовчуванням, визначені стандартом:
Uuid::NAMESPACE_DNS
якщо ви генеруєте UUID для сутностей DNSUuid::NAMESPACE_URL
якщо ви генеруєте UUID для URLUuid::NAMESPACE_OID
якщо ви генеруєте UUID для OID (ідентифікатори обʼєктів)Uuid::NAMESPACE_X500
якщо ви генеруєте UUID для X500 DNs (визначені імена)
UUID v4 (довільний)
Генерує довільний UUID (читайте специфікацію UUIDv4). Завдяки своїй довільності він забезпечує унікальність у розподілених системах без необхідності в центральному координуючому органі. Це безпечно для приватності, оскільки не містить жодної інформації про те, де і коли він був згенерований:
1 2 3 4
use Symfony\Component\Uid\Uuid;
// $uuid is an instance of Symfony\Component\Uid\UuidV4
$uuid = Uuid::v4();
UUID v5 (заснований на імені, SHA-1)
Це те ж саме, що і UUIDv3 (описано вище), але використовує sha1
замість
md5
для хешування заданого простору імен та імені (читайте специфікацію UUIDv5).
Це робить його більш безпечним і менш схильним до хеш-колізій.
UUID v6 (переупорядкований, засновний на часі)
Переставляє поля UUIDv1 на основі часу, щоб зробити його лексикографічно сортованим (як ULID). Це більш ефективно для індексації бази даних (читайте специфікацію UUIDv6):
1 2 3 4
use Symfony\Component\Uid\Uuid;
// $uuid є екземпляром Symfony\Component\Uid\UuidV6
$uuid = Uuid::v6();
Tip
Рекомендується використовувати UUIDv7 замість UUIDv6, оскільки він забезпечує кращу ентропію.
UUID v7 (часова мітка UNIX)
Генерує впорядковані за часом UUID на основі джерела часової мітки Unix Epoch з високою роздільною здатністю (кількість мілісекунд з опівночі 1 січня 1970 року за UTC, високосні секунди не враховуються) (читайте специфікацію UUIDv7). Рекомендується використовувати цю версію замість UUIDv1 і UUIDv6, оскільки вона забезпечує кращу ентропію (і більш строгий хронологічний порядок генерації UUID):
1 2 3 4
use Symfony\Component\Uid\Uuid;
// $uuid є екземпляром Symfony\Component\Uid\UuidV7
$uuid = Uuid::v7();
UUID v8 (користувацький)
Надає RFC-сумісний формат для експериментальних або специфічних для постачальника випадків використання (читайте специфікацію UUIDv8). Єдиною вимогою є встановлення варіанту та версії бітів в UUID. Решта значень UUID є специфічним для кожної реалізації, і не слід припускати будь-який формат :
1 2 3 4
use Symfony\Component\Uid\Uuid;
// $uuid є екземпляром Symfony\Component\Uid\UuidV8
$uuid = Uuid::v8();
Якщо ваше значення UUID вже згенероване в іншому форматі, використайте будь-який з
наступних методів, щоб створити з нього обʼєкт Uuid
:
1 2 3 4 5 6
// всі наступні приклади згенерують однаковий обʼєкт Uuid
$uuid = Uuid::fromString('d9e7a184-5d5b-11ea-a62a-3499710062d0');
$uuid = Uuid::fromBinary("\xd9\xe7\xa1\x84\x5d\x5b\x11\xea\xa6\x2a\x34\x99\x71\x00\x62\xd0");
$uuid = Uuid::fromBase32('6SWYGR8QAV27NACAHMK5RG0RPG');
$uuid = Uuid::fromBase58('TuetYWNHhmuSQ3xPoVLv9M');
$uuid = Uuid::fromRfc4122('d9e7a184-5d5b-11ea-a62a-3499710062d0');
Ви також можете використати UuidFactory
для генерування UUID. Спочатку ви можете
сконфігурувати поведінку фабрики, використовуючи файли конфігурації:
1 2 3 4 5 6 7 8
# config/packages/uid.yaml
framework:
uid:
default_uuid_version: 7
name_based_uuid_version: 5
name_based_uuid_namespace: 6ba7b810-9dad-11d1-80b4-00c04fd430c8
time_based_uuid_version: 7
time_based_uuid_node: 121212121212
Потім ви можете впровадити фабрику у ваші сервіси та використовувати її для генерування UUID, засновуючись на визначеній вами конфігурації:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23
namespace App\Service;
use Symfony\Component\Uid\Factory\UuidFactory;
class FooService
{
public function __construct(
private UuidFactory $uuidFactory,
) {
}
public function generate(): void
{
// Це створить UUID версії, наданої у файлі конфігурації (за замовчуванням v6)
$uuid = $this->uuidFactory->create();
$nameBasedUuid = $this->uuidFactory->nameBased(/** ... */);
$randomBasedUuid = $this->uuidFactory->randomBased();
$timestampBased = $this->uuidFactory->timeBased();
// ...
}
}
Конвертація UUID
Використайте ці методи, щоб перетворити обʼєкти UUID на різні основи:
1 2 3 4 5 6 7 8
$uuid = Uuid::fromString('d9e7a184-5d5b-11ea-a62a-3499710062d0');
$uuid->toBinary(); // string(16) "\xd9\xe7\xa1\x84\x5d\x5b\x11\xea\xa6\x2a\x34\x99\x71\x00\x62\xd0"
$uuid->toBase32(); // string(26) "6SWYGR8QAV27NACAHMK5RG0RPG"
$uuid->toBase58(); // string(22) "TuetYWNHhmuSQ3xPoVLv9M"
$uuid->toRfc4122(); // string(36) "d9e7a184-5d5b-11ea-a62a-3499710062d0"
$uuid->toHex(); // string(34) "0xd9e7a1845d5b11eaa62a3499710062d0"
$uuid->toString(); // string(36) "d9e7a184-5d5b-11ea-a62a-3499710062d0"
7.1
Метод toString()
було представлено в Symfony 7.1.
Ви також можете перетворити деякі версії UUID на інші:
1 2 3 4 5 6 7 8 9 10
// перетворити V1 на V6 або V7
$uuid = Uuid::v1();
$uuid->toV6(); // повертає екземпляр Symfony\Component\Uid\UuidV6
$uuid->toV7(); // повертає екземпляр Symfony\Component\Uid\UuidV7
// перетворити V6 на V7
$uuid = Uuid::v6();
$uuid->toV7(); // повертає екземпляр Symfony\Component\Uid\UuidV7
Робота з UUID
UUID-обʼєкти, створені класом Uuid
можуть використовувати наступні методи (які
еквівалентні методу uuid_*()
PHP-розширення):
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27
use Symfony\Component\Uid\NilUuid;
use Symfony\Component\Uid\Uuid;
// перевірка, чи є UUID null (відмітьте, що клас називається
// NilUuid замість NullUuid, щоб слідувати стандартній нотації UUID)
$uuid = Uuid::v4();
$uuid instanceof NilUuid; // false
// перевірка типу UUID
use Symfony\Component\Uid\UuidV4;
$uuid = Uuid::v4();
$uuid instanceof UuidV4; // true
// отримання дати та часу UUID (доступно лише в деяких типах UUID)
$uuid = Uuid::v1();
$uuid->getDateTime(); // returns a \DateTimeImmutable instance
// порівняння UUID та перевірка рівності
$uuid1 = Uuid::v1();
$uuid4 = Uuid::v4();
$uuid1->equals($uuid4); // false
// цей метод повертає:
// * int(0), якщо $uuid1 і $uuid4 рівні
// * int > 0, якщо $uuid1 більше, ніж $uuid4
// * int < 0, якщо $uuid1 менше, ніж $uuid4
$uuid1->compare($uuid4); // наприклад, int(4)
Зберігання UUID в базах даних
Якщо ви використовуєте Doctrine, розгляньте використання типу Doctrine
uuid
, який перетворює з/на обʼєкти UUID автоматично:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15
// src/Entity/Product.php
namespace App\Entity;
use Doctrine\ORM\Mapping as ORM;
use Symfony\Bridge\Doctrine\Types\UuidType;
use Symfony\Component\Uid\Uuid;
#[ORM\Entity(repositoryClass: ProductRepository::class)]
class Product
{
#[ORM\Column(type: UuidType::NAME)]
private Uuid $someProperty;
// ...
}
Також існує генератор Doctrine, щоб допомогти з автоматичним генеруванням значень UUID для основних ключів сутності:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21
namespace App\Entity;
use Doctrine\ORM\Mapping as ORM;
use Symfony\Bridge\Doctrine\Types\UuidType;
use Symfony\Component\Uid\Uuid;
class User implements UserInterface
{
#[ORM\Id]
#[ORM\Column(type: UuidType::NAME, unique: true)]
#[ORM\GeneratedValue(strategy: 'CUSTOM')]
#[ORM\CustomIdGenerator(class: 'doctrine.uuid_generator')]
private ?Uuid $id;
public function getId(): ?Uuid
{
return $this->id;
}
// ...
}
При використанні вбудованих методів сховища Doctrine (наприклад, findOneBy()
),
Doctrine знає, як перетворювати ці типи UUID, щоб створити SQL-запит (наприклад,
->findOneBy(['user' => $user->getUuid()])
). Однак, при використанні DQL-запитів,
або створенні запиту самостійно, вам знадобиться встановити uuid
як тип UUID-параметрів:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24
// src/Repository/ProductRepository.php
// ...
use Symfony\Bridge\Doctrine\Types\UuidType;
class ProductRepository extends ServiceEntityRepository
{
// ...
public function findUserProducts(User $user): array
{
$qb = $this->createQueryBuilder('p')
// ...
// додайте 'uuid' як третій аргумент, щоб повідомити Doctrine, що це UUID
->setParameter('user', $user->getUuid(), UuidType::NAME)
// як варіант, ви можете перетворити його на значення, сумісне з
// типом, визначеним Doctrine
->setParameter('user', $user->getUuid()->toBinary())
;
// ...
}
}
ULID
ULID (Універсально унікальні лексикографічно сортовані ідентифікатори) - це
128-бітні числа, зазвичай представлені у вигляді рядків з 26 знаків: TTTTTTTTTTRRRRRRRRRRRRRRRR
(де T
- це часова відмітка, а R
- рандомні біти).
ULID - це альтернатива UUID, коли використання останніх не є практичним. Вони представляють 128-бітну сумісність з UUID, лексикографічно сортовані та зашифровані як рядки з 26 знаків (проти 36-знакових UUID).
Note
Якщо ви генеруєте більше одного ULID під час однієї мілісекунди у простому процесі, тоді рандомна частина збільшується на один біт, щоб надати монотонність для сортування. В такому випадку, рандомна частина не настільки випадкова, як у порівнянні з попереднім ULID.
Створення ULID
Інстанціюйте клас Ulid
, щоб згенерувати рандомне значення ULID:
1 2 3
use Symfony\Component\Uid\Ulid;
$ulid = new Ulid(); // наприклад, 01AN4Z07BY79KA1307SR9X4MV3
Якщо ваше значення ULID вже згенероване в іншому форматі, використайте будь-який
з наступних методів, щоб створити з нього обʼєкт Ulid
:
1 2 3 4 5 6
// всі наступні приклади створять однаковий обʼєкт Ulid
$ulid = Ulid::fromString('01E439TP9XJZ9RPFH3T1PYBCR8');
$ulid = Ulid::fromBinary("\x01\x71\x06\x9d\x59\x3d\x97\xd3\x8b\x3e\x23\xd0\x6d\xe5\xb3\x08");
$ulid = Ulid::fromBase32('01E439TP9XJZ9RPFH3T1PYBCR8');
$ulid = Ulid::fromBase58('1BKocMc5BnrVcuq2ti4Eqm');
$ulid = Ulid::fromRfc4122('0171069d-593d-97d3-8b3e-23d06de5b308');
Як і UUID, ULID мають свою власну фабрику, UlidFactory
, яка може бути використана
для їхнього генерування:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18
namespace App\Service;
use Symfony\Component\Uid\Factory\UlidFactory;
class FooService
{
public function __construct(
private UlidFactory $ulidFactory,
) {
}
public function generate(): void
{
$ulid = $this->ulidFactory->create();
// ...
}
}
Також існує спеціальний клас NilUlid
, щоб представляти значення ULID null
:
1 2 3 4
use Symfony\Component\Uid\NilUlid;
$ulid = new NilUlid();
// еквівалентно $ulid = new Ulid('00000000000000000000000000');
Конвертація ULID
Використовуйте ці методи, щоб перетворити обʼєкт ULID на різні основи:
1 2 3 4 5 6 7
$ulid = Ulid::fromString('01E439TP9XJZ9RPFH3T1PYBCR8');
$ulid->toBinary(); // string(16) "\x01\x71\x06\x9d\x59\x3d\x97\xd3\x8b\x3e\x23\xd0\x6d\xe5\xb3\x08"
$ulid->toBase32(); // string(26) "01E439TP9XJZ9RPFH3T1PYBCR8"
$ulid->toBase58(); // string(22) "1BKocMc5BnrVcuq2ti4Eqm"
$ulid->toRfc4122(); // string(36) "0171069d-593d-97d3-8b3e-23d06de5b308"
$ulid->toHex(); // string(34) "0x0171069d593d97d38b3e23d06de5b308"
Робота з ULID
ULID-обʼєкти, створені класом Ulid
, можуть використовувати наступні методи:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15
use Symfony\Component\Uid\Ulid;
$ulid1 = new Ulid();
$ulid2 = new Ulid();
// перевірка, чи є задане значення валідним як ULID
$isValid = Ulid::isValid($ulidValue); // true або false
// отримання часу та дати ULID
$ulid1->getDateTime(); // повертає \DateTimeImmutable instance
// порівняння ULID та перевірка рівності
$ulid1->equals($ulid2); // false
// this method returns $ulid1 <=> $ulid2
$ulid1->compare($ulid2); // наприклад, int(-1)
Зберігання ULID в базах даних
Якщо ви використовуєте Doctrine, розгляньте використання типу Doctrine
ulid
, який автоматично перетворить з/на ULID-обʼєкти:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15
// src/Entity/Product.php
namespace App\Entity;
use Doctrine\ORM\Mapping as ORM;
use Symfony\Bridge\Doctrine\Types\UlidType;
use Symfony\Component\Uid\Ulid;
#[ORM\Entity(repositoryClass: ProductRepository::class)]
class Product
{
#[ORM\Column(type: UlidType::NAME)]
private Ulid $someProperty;
// ...
}
Також існує генератор Doctrine, щоб допомогти з автоматичним генеруванням ULID-значень для головних ключів сутностей:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22
namespace App\Entity;
use Doctrine\ORM\Mapping as ORM;
use Symfony\Bridge\Doctrine\Types\UlidType;
use Symfony\Component\Uid\Ulid;
class Product
{
#[ORM\Id]
#[ORM\Column(type: UlidType::NAME, unique: true)]
#[ORM\GeneratedValue(strategy: 'CUSTOM')]
#[ORM\CustomIdGenerator(class: 'doctrine.ulid_generator')]
private ?Ulid $id;
public function getId(): ?Ulid
{
return $this->id;
}
// ...
}
При використанні вбудованих методів сховища Doctrine (наприклад, findOneBy()
),
Doctrine знає, як перретворити ці ULID-типи для створення SQL-запиту (наприклад,
->findOneBy(['user' => $user->getUlid()])
). Однак, при використанні DQL-запитів,
вам потрібно буде встановити ulid
як тип ULID-параметрів:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22
// src/Repository/ProductRepository.php
// ...
class ProductRepository extends ServiceEntityRepository
{
// ...
public function findUserProducts(User $user): array
{
$qb = $this->createQueryBuilder('p')
// ...
// додайте 'ulid' як третій аргумент, щоб повідомити Doctrine, що це ULID
->setParameter('user', $user->getUlid(), 'ulid')
// як варіант, ви можете перетворити його на значення, сумісне з типом,
// визначеним Doctrine
->setParameter('user', $user->getUlid()->toBinary())
;
// ...
}
}
Генерування та дослідження UUID/ULID в консолі
Этот компонент предоставляет несколько команд для генерирования и исследования UUID/ULID в консоли. Они не включены по умолчанию, поэтому вы должны добавить следующую конфигурацию в вашем приложении перед тем, как использовать эти команды:
1 2 3 4 5 6
# config/services.yaml
services:
Symfony\Component\Uid\Command\GenerateUlidCommand: ~
Symfony\Component\Uid\Command\GenerateUuidCommand: ~
Symfony\Component\Uid\Command\InspectUlidCommand: ~
Symfony\Component\Uid\Command\InspectUuidCommand: ~
Тепер ви можете генерувати UUID/ULID наступним чином (додайте опцію --help
до команд, щоб дізнатисся все про їх опції):
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17
# згенерувати 1 рандомно-заснований UUID
$ php bin/console uuid:generate --random-based
# згенерувати 1 UUID, заснований на часі, з конкретним вузлом
$ php bin/console uuid:generate --time-based=now --node=fb3502dc-137e-4849-8886-ac90d07f64a7
# згенерувати 2 UUID та вивессти їх у форматі base58
$ php bin/console uuid:generate --count=2 --format=base58
# згенерувати 1 ULID з поточним часом в якості часової відмітки
$ php bin/console ulid:generate
# згенерувати 1 ULID з конкретною часовою відміткою
$ php bin/console ulid:generate --time="2021-02-02 14:00:00"
# згенерувати 2 ULID та вивести їх у форматі RFC4122
$ php bin/console ulid:generate --count=2 --format=rfc4122
На додаток до створення нових UID, ви також можете дослідити їх за допомогою наступних команд, щоб побачити всю інформацію про заданий UID:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20
$ php bin/console uuid:inspect d0a3a023-f515-4fe0-915c-575e63693998
------------------------- --------------------------------------
Ярлик Значення
------------------------- --------------------------------------
Версія 4
Канонікал (RFC 4122) d0a3a023-f515-4fe0-915c-575e63693998
База 58 SmHvuofV4GCF7QW543rDD9
База 32 6GMEG27X8N9ZG92Q2QBSHPJECR
------------------------- --------------------------------------
$ php bin/console ulid:inspect 01F2TTCSYK1PDRH73Z41BN1C4X
------------------------ --------------------------------------
Ярлик Значення
------------------------ --------------------------------------
Канонікал (База 32) 01F2TTCSYK1PDRH73Z41BN1C4X
База 58 1BYGm16jS4kX3VYCysKKq6
RFC 4122 0178b5a6-67d3-0d9b-889c-7f205750b09d
------------------------ --------------------------------------
Часова відмітка. 2021-04-09 08:01:24.947
------------------------ --------------------------------------