Компонент UID
Дата обновления перевода 2023-01-19
Компонент UID
Компонент UID предоставляет утилиты для работы с уникальными идентификаторами (UID), вроде 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:
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 28 29 30 31 32 33 34 35 36 37 38 39 40
use Symfony\Component\Uid\Uuid;
// UUID 1го типа генерирует UUID, используя MAC-адрес вашего устройства и временную отметку.
// Оба получаются автоматически, поэтому вам не нужно передавать никакие аргументы конструктора.
$uuid = Uuid::v1(); // $uuid is an instance of Symfony\Component\Uid\UuidV1
// UUID 4го типа генерирует рандомный UUID, поэтому вам не нужно передавать никакие аргументы конструктора.
$uuid = Uuid::v4(); // $uuid is an instance of Symfony\Component\Uid\UuidV4
// UUID 3го и 5го типов генерируют UUID, хещируя заданное пространство имен и имя. 3й тип использует
// MD5-хеши, а 5й тип использует SHA-1. Пространство имен - это еще один UUID (например, UUID 4го типа),
// а имя - произвольная строка (например, название продукта; если оно уникально).
$namespace = Uuid::v4();
$name = $product->getUniqueName();
$uuid = Uuid::v3($namespace, $name); // $uuid is an instance of Symfony\Component\Uid\UuidV3
$uuid = Uuid::v5($namespace, $name); // $uuid is an instance of Symfony\Component\Uid\UuidV5
// пространства имён, определенные RFC 4122 (см. https://tools.ietf.org/html/rfc4122#appendix-C)
// доступны как PHP-константы и как значения строк
$uuid = Uuid::v3(Uuid::NAMESPACE_DNS, $name); // same as: Uuid::v3('dns', $name);
$uuid = Uuid::v3(Uuid::NAMESPACE_URL, $name); // same as: Uuid::v3('url', $name);
$uuid = Uuid::v3(Uuid::NAMESPACE_OID, $name); // same as: Uuid::v3('oid', $name);
$uuid = Uuid::v3(Uuid::NAMESPACE_X500, $name); // same as: Uuid::v3('x500', $name);
// UUID 6го типа не являются частью стандарта UUID. Он лексикографически сортируемый
// (как ULID) и содержит 60-битную временную отметку вместе с 63 дополнительными уникальными битами.
// Он определяется в http://gh.peabody.io/uuidv6/
$uuid = Uuid::v6(); // $uuid is an instance of Symfony\Component\Uid\UuidV6
// UUID версии 7 представляет поле значения, упорядоченное по времени, выведенное из хорошо известного
// источника временной отметки Unix Epoch: количество секунд с полуночи 1 января 1970 UTC, високосные секунды исключены.
// А также улучшенные характеристики энтропии по сравнению с версиями 1 и 6.
$uuid = Uuid::v7();
// UUID версии 8 предоставляет формат, совместимый с RFC, для экспериментальных случаев использования, для конкретных поставщиков.
// Единственное требование - биты варианта и версии ДОЛЖНЫ быть установлены, как определено в Разделе 4:
// https://www.ietf.org/archive/id/draft-peabody-dispatch-new-uuid-format-04.html#variant_and_version_fields
// уникальность UUIDv8 будет зависеть от реализации и НЕ ДОЛЖНА предполагаться.
$uuid = Uuid::v8();
6.2
Версии UUID 7 и 8 были представлены в Symfony 6.2.
Если ваше значение 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');
Конвертация UUID
Используйте эти методы, чтобы преобразовать объекты UUID в разные основы:
1 2 3 4 5 6 7 8 9
$uuid = Uuid::fromString('d9e7a184-5d5b-11ea-a62a-3499710062d0');
$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"
6.2
Метод toHex()
был представлен в Symfony 6.2.
Работа с 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 28 29 30
use Symfony\Component\Uid\NilUuid;
use Symfony\Component\Uid\Uuid;
// проверка, является ли UUID null (отметьте, что класс называется
// NilUuid вместо NullUuid, чтобы следовать cтандартной нотации 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
$isValid = Uuid::isValid($uuid); // true or false
// сравнение 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 16 17
// src/Entity/Product.php
namespace App\Entity;
use Doctrine\ORM\Mapping as ORM;
/**
* @ORM\Entity(repositoryClass="App\Repository\ProductRepository")
*/
class Product
{
/**
* @ORM\Column(type="uuid")
*/
private $someProperty;
// ...
}
6.2
Константа UuidType::NAME
была представлена в Symfony 6.2.
Также существует генератор 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 $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(), 'uuid')
// как вариант, вы можете преобразовать его в значение, совместимое с
// типом, определенным 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');
Также существует специальный класс 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"
6.2
Метод toHex()
был представлен в Symfony 6.2.
Работа с 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 or false
// получение времени и даты ULID
$ulid1->getDateTime(); // returns a \DateTimeImmutable instance
// сравнение ULID и проверка равенства
$ulid1->equals($ulid2); // false
// this method returns $ulid1 <=> $ulid2
$ulid1->compare($ulid2); // e.g. int(-1)
Хранение ULID в базах данных
Если вы используете Doctrine, рассмотрите использование типа Doctrine
ulid
, который автотматически преобразует в/из ULID-объекты:
1 2 3 4 5 6 7 8 9 10 11 12 13 14
// src/Entity/Product.php
namespace App\Entity;
use Doctrine\ORM\Mapping as ORM;
use Symfony\Bridge\Doctrine\Types\UlidType;
#[ORM\Entity(repositoryClass: ProductRepository::class)]
class Product
{
#[ORM\Column(type: UlidType::NAME)]
private $someProperty;
// ...
}
6.2
Константа UlidType::NAME
была представлена в Symfony 6.2.
Также существует генератор 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 $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 23 24
// src/Repository/ProductRepository.php
// ...
use Symfony\Bridge\Doctrine\Types\UlidType;
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 в консоли. Они не включены по умолчанию, поэтому вы должны добавить следующую конфигурацию в вашем приложении перед тем, как использовать эти команды:
- YAML
- XML
- PHP
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
------------------------ --------------------------------------