krmgns/uuid

带日期/时间前缀的随机或可排序的UUID。

1.4.3 2024-02-01 03:19 UTC

This package is auto-updated.

Last update: 2024-09-07 21:33:24 UTC


README

在保留生成值版本和变体字段的同时,Uuid库以简单快捷的方法提供三种类型的UUID,可用于需要可排序UUID的地方。

generate() 方法:

  • Uuid\Uuid 类使用16位长度的随机字节(UUID/v4)。
  • Uuid\DateUuid 类使用12位长度的随机字节和4位长度的UTC日期字节作为前缀,生成的值可排序到第8个十六进制字符。
  • Uuid\DateTimeUuid 类使用10位长度的随机字节和6位长度的UTC日期/时间字节作为前缀,生成的值可排序到第12个十六进制字符。

除了这些UUID可排序外,它们还可以用于某些工作,如文件夹探索(例如,在与图像裁剪服务一起工作时)。

因此,让我们通过一个快速示例来了解一下它的实际应用:

// File: ImageController.php
use Uuid\{DateUuid, UuidError};
use Throwable;

/**
 * Eg: cdn.foo.com/image/crop/0134b3ce-ce20-4917-a020-f0514e110834.jpg
 * @route /image/crop/:image
 */
public function cropAction(string $image) {
    // Eg: 0134b3ce-ce20-4917-a020-f0514e110834.jpg
    [$name, $extension] = explode('.', $image);

    try {
        // Since we've created an image file name with DateUuid,
        // here we're expecting the incoming $image to be valid.
        $uuid = new DateUuid($name);

        // Eg: 2023/11/12
        $path = $uuid->getDate('/');
    } catch (UuidError) {
        // Invalid DateUuid.
        throw new BadRequestError();
    } catch (Throwable) {
        // Internal error.
        throw new InternalServerError();
    }

    // Eg: /images/2023/11/12/0134b3ce-ce20-4917-a020-f0514e110834.jpg
    $image = sprintf('/images/%s/%s.%s', $path, $name, $extension);

    // No such file.
    if (!file_exists($image)) {
        throw new NotFoundError();
    }

    // Else crop image & serve cropped image here...
}

安装

composer require krmgns/uuid

注意/提醒

· 除了所有类都可以接受 $value 参数(#1)作为 string 类型外,Uuid\Uuid 类还可以接受 Uuid\Uuid 类型,Uuid\DateUuid 类也可以接受 Uuid\DateUuid 类型,Uuid\DateTimeUuid 类也可以接受 Uuid\DateTimeUuid 类型,但也可以省略以自动生成。

· 除了 Uuid\Uuid 实现了 Stringable 接口外,Uuid\DateUuidUuid\DateTimeUuidUuid\Uuid 类的子类。因此,它们继承了一些有用的方法(如 toString()toHashString() 等),同时也覆盖了一些方法(如 isValid()generate()validate() 等)以及构造方法。

· 由于 Uuid\DateTimeUuid 使用秒级别的即时日期/时间戳(格式:YmdHis),最好的可排序UUID只能通过这个类生成。

Uuid\Uuid

与继承类一样,如果没有提供 $value(UUID值),则 Uuid\Uuid 类将自行生成并分配其值。否则,给定值将在严格模式下检查(修饰符参数是 $strict,值为 true)是否为有效的UUID值后分配。

use Uuid\{Uuid, UuidError};

// Auto-generate.
$uuid = new Uuid();

assert($uuid->value === $uuid->toString());
assert($uuid->value === (string) $uuid);
assert($uuid->value == $uuid); // Stringable

assert(true === $uuid->isEqual($uuid));
assert(true === $uuid->isEqual($uuid->value));

$uuid = new Uuid('26708ec6-ad78-4291-a449-9ee08cf50cfc');
assert(true === $uuid->isValid());

$uuid = new Uuid('invalid', strict: false);
assert(false === $uuid->isValid());

try { new Uuid(null); } catch (UuidError $e) {
    assert("Invalid UUID value: null" === $e->getMessage());
}

try { new Uuid('invalid'); } catch (UuidError $e) {
    assert("Invalid UUID value: 'invalid'" === $e->getMessage());
}

// Given value.
$uuid = new Uuid($value = '26708ec6-ad78-4291-a449-9ee08cf50cfc');

assert(true === $uuid->isEqual($uuid));
assert(true === $uuid->isEqual($uuid->value));
assert(true === $uuid->isEqual($value));

assert('26708ec6-ad78-4291-a449-9ee08cf50cfc' === $uuid->toString());
assert('26708ec6ad784291a4499ee08cf50cfc' === $uuid->toHashString());

// Null values.
$uuid1 = new Uuid('00000000-0000-0000-0000-000000000000', strict: false);
$uuid2 = new Uuid('00000000000000000000000000000000', strict: false);

assert(false === $uuid1->isValid());
assert(false === $uuid2->isValid());

assert(true === $uuid1->isNull());
assert(true === $uuid2->isNullHash());

assert(Uuid::NULL === $uuid1->value);
assert(Uuid::NULL_HASH === $uuid2->value);

静态

// Generating.
$uuid = Uuid::generate(); // Eg: fec3cfe2-d378-4181-8ba1-99c54bcfa63e

// Validating.
$valid = Uuid::validate($uuid);
assert(true === $valid);

assert(false === Uuid::validate('invalid'));
assert(false === Uuid::validate('invalid', strict: false));

assert(false === Uuid::validate(Uuid::NULL));
assert(false === Uuid::validate(Uuid::NULL_HASH));

assert(true === Uuid::validate(Uuid::NULL, strict: false));
assert(true === Uuid::validate(Uuid::NULL_HASH, strict: false));

// Equal checking.
assert(true === Uuid::equals($uuid, 'fec3cfe2-d378-4181-8ba1-99c54bcfa63e'));
assert(false === Uuid::equals($uuid, 'invalid-uuid-input-value'));

// DIY tools.
$bins = random_bytes(16);

// Add version/variant.
$bins = Uuid::modify($bins);

// Format as UUID format.
$uuid = Uuid::format(bin2hex($bins));

有关更多示例,请参阅 test/unit/UuidTest.php

Uuid\DateUuid

这个类使用12位长度的随机字节和4位长度的UTC日期字节作为前缀。因此,其日期可以重新提取(例如:20231212 或 2023-12-12,使用 $separator 选项),可用于任何用例,且适用于需要可排序UUID的地方。

use Uuid\DateUuid;

$date = explode('.', gmdate('Y.m.d'));
$time = explode('.', gmdate('00:00:00'));

// Getting date.
$uuid = new DateUuid();

assert($date === $uuid->getDate());
assert(implode('/', $date) === $uuid->getDate(separator: '/'));

$uuid = new DateUuid('d41d8cd98f00b204e9800998ecf8427e', strict: false);

assert(null === $uuid->getDate());

// Getting date/time.
$uuid = new DateUuid();

assert(implode('-', $date) === $uuid->getDateTime()->format('Y-m-d'));
assert(implode(':', $time) === $uuid->getDateTime()->format('H:i:s'));

$uuid = new DateUuid('d41d8cd98f00b204e9800998ecf8427e', strict: false);

assert(null === $uuid->getDateTime());

静态

// Generating.
$uuid = DateUuid::generate(); // Eg: 0134b3ce-25fc-49f8-b9f9-61ed2784c7d1

// Parsing.
$uuid1 = new DateUuid();
$uuid2 = new DateUuid('d41d8cd98f00b204e9800998ecf8427e', strict: false);

assert(null !== DateUuid::parse($uuid1->value));
assert(null === DateUuid::parse($uuid2->value));

// Next year for falsity (eg: 20241212).
$threshold = (gmdate('Y') + 1) . '1212';

assert(null === DateUuid::parse($uuid1->value, $threshold));

有关更多示例,请参阅 test/unit/DateUuidTest.php

Uuid\DateTimeUuid

这个类使用10位长度的随机字节和6位长度的UTC日期/时间字节作为前缀。因此,其日期可以重新提取(例如:20231212、101122 或 2023-12-12、10-11-22,使用 $separator 选项),可用于任何用例,且适用于需要可排序UUID的地方。

use Uuid\DateTimeUuid;

$date = explode('.', gmdate('Y.m.d'));
$time = explode('.', gmdate('H.i.s'));

// Getting date.
$uuid = new DateTimeUuid();

assert($date === $uuid->getDate());
assert(implode('/', $date) === $uuid->getDate(separator: '/'));

$uuid = new DateTimeUuid('d41d8cd98f00b204e9800998ecf8427e', strict: false);

assert(null === $uuid->getDate());

// Getting time.
$uuid = new DateTimeUuid();

assert($time === $uuid->getTime());
assert(implode(':', $time) === $uuid->getTime(separator: ':'));

$uuid = new DateTimeUuid('d41d8cd98f00b204e9800998ecf8427e', strict: false);

assert(null === $uuid->getTime());

// Getting date/time.
$uuid = new DateTimeUuid();

assert(implode('-', $date) === $uuid->getDateTime()->format('Y-m-d'));
assert(implode(':', $time) === $uuid->getDateTime()->format('H:i:s'));

$uuid = new DateTimeUuid('d41d8cd98f00b204e9800998ecf8427e', strict: false);

assert(null === $uuid->getDateTime());

静态

// Generating.
$uuid = DateTimeUuid::generate(); // Eg: 12666c9c-b0c6-4532-b8da-dbc660ff4170

// Parsing.
$uuid1 = new DateTimeUuid();
$uuid2 = new DateTimeUuid('d41d8cd98f00b204e9800998ecf8427e', strict: false);

assert(null !== DateTimeUuid::parse($uuid1->value));
assert(null === DateTimeUuid::parse($uuid2->value));

// Next year for falsity (eg: 20241212191919).
$threshold = (gmdate('Y') + 1) . '1212191919';

assert(null === DateTimeUuid::parse($uuid1->value, $threshold));

有关更多示例,请参阅 test/unit/DateTimeUuidTest.php