昨天我尝试做 Symfony 在一些博客文章中喊出的事情(https://symfony.com/blog/new-in-symfony-5-2-doctrine-types-for-uuid-and-ulid)但是失败了。我想在数据库中存储 ULID(格式“TTTTTTTTTTRRRRRRRRRRRRRRRR”),因为它们不仅可以排序,而且还包含一个非常适合我的应用程序的时间戳。但是,当我告诉属性为“type=ulid”时,它将作为 UUID(格式:“xxxxxxxx-xxxx-Mxxx-Nxxx-xxxxxxxxxxxx”)存储在数据库中。
我调试了半天,对此很恼火,我从头开始,问题仍然存在。
我哪里出错了?
(如果您愿意,请跳到 ULID 标题,以下内容可能看起来很长,但其中 50% 只是基本内容)
我一遍又一遍地做的事情取自https://symfony.com/doc/5.4/setup.html:
stat shyt # 不存在composer 创建项目 symfony/sculpture:5.4.* shytcd shyt;作曲家需要 webappbin/console about 显示 Symfony 版本 5.4.10 和 PHP 7.4取自https://symfony.com/doc/5.4/doctrine.html:
composer 需要 symfony/orm-packcomposer 需要 --dev symfony/maker-bundledocker-compose up -d错误:在分配给网络的默认地址池中找不到可用的、不重叠的 IPv4 地址池
所以我在 docker-compose.override.yml 文件中添加了一些行:
networks:
default:
ipam:
config:
- subnet: 10.1.2.1/24
services:
database:
# [...] doctrine/doctrine-bundle stuff [...]
networks:
default:
ipv4_address: 10.1.2.3
bin/console 学说:数据库:create(很愚蠢,但如文档所述)无法为名为default的连接创建数据库“app” 执行查询时发生异常:SQLSTATE[42P04]:重复数据库:7错误:数据库“app”已存在
嗯,是的。 Docker 已经做到了这一点。
make:entity 被推迟,直到我们拥有 ULID 功能。我们已经倾向于 https://symfony.com/doc/5.4/components/uid.html (尤其是 ULID 部分):
composer 需要 symfony/uidbin/console make:entity Product看起来几乎与文档中的一样,只是它有一个附加字段(主键,一个整数)和一些 getter/setter。
在这之间,我们使用测试以编程方式创建数据库条目:
composer 需要 phpunit 以编程方式创建数据库条目bin/console --env=测试主义:migrations:migratebin/console --env=测试主义:数据库:create<?php
namespace AppTests;
use AppEntityProduct;
use AppRepositoryProductRepository;
use DoctrineORMEntityManager;
use SymfonyBundleFrameworkBundleTestKernelTestCase;
use SymfonyComponentUidUlid;
class FooTest extends KernelTestCase
{
public function testFoo(): void
{
$product = new Product();
$product->setSomeProperty(new Ulid());
static::assertNotNull($product->getSomeProperty());
self::getContainer()->get(ProductRepository::class)
->add($product);
self::getContainer()->get('doctrine.orm.entity_manager')
->flush();
}
}
bin/console --env=test 主义:query:sql 'TRUNCATE Product' 只是为了确定bin/phpunitbin/console --env=测试主义:query:sql 'SELECT * FROM 产品'显示 UUID,而不是 ULID。
在数据库中显示 ULID 而不是 UUID
首先清理一下,然后执行 https://symfony.com/doc/5.4/components/uid.html#ulids 中所示的示例:
rm 迁移/* 重新开始bin/console --env=测试主义:database:drop --forcebin/console --env=测试主义:数据库:createbin/控制台主义:数据库:drop --forcebin/console --env=测试主义:数据库:create<?php
namespace AppEntity;
use DoctrineORMMapping as ORM;
use SymfonyComponentUidUlid;
use AppRepositoryProductRepository;
/**
* @ORMEntity(repositoryClass=ProductRepository::class)
*/
class Product
{
/**
* @ORMId
* @ORMColumn(type="ulid", unique=true)
* @ORMGeneratedValue(strategy="CUSTOM")
* @ORMCustomIdGenerator(class="doctrine.ulid_generator")
*/
private $id;
public function getId(): ?Ulid
{
return $this->id;
}
// ...
}
(文档中的示例缺少存储库行)
bin/console make:migrationbin/console --env=测试主义:migrations:migratepublic function testFoo(): void
{
self::getContainer()->get(ProductRepository::class)
->add(new Product());
self::getContainer()->get('doctrine.orm.entity_manager')
->flush();
}
bin/phpunit(有风险也可以)bin/console --env=测试主义:query:sql 'SELECT * FROM 产品'再次使用 UUID 而不是 ULID
数据库显示 UUID 而不是 ULID
Copyright 2014-2025 https://www.php.cn/ All Rights Reserved | php.cn | 湘ICP备2023035733号
有点晚了,但对于面临这个问题的人来说,我也有显示 UUID 而不是 ULID 的数据库,这似乎是学说中的预期行为,因为您可以互换使用 UUID/ULID,这意味着即使您将 UUID 存储在数据库,但您的实体映射到 ULID,从数据库检索对象时您将拥有 ULID,您也可以使用 ULID 或 UUID 检索相同的对象。
例如,我有一个用户实体,其标识符具有 ULID,因此存储的对象将具有如下 uuid:
如果我使用该 UUID 检索我的用户,我将得到:
App\Entity\User {#430 ▼ -id: "01GHVYDVNW2S615RS2SA7HN27K" -email: "myemail@mail.com" -roles: [] #createdAt: DateTime @1668458933 {#423 ▶} #updatedAt: DateTime @1668458998 {#428 ▶} -password: "$2y$13$/2i9Ovc2lCQBRfSVgsnmoul1FhF.Kyki3irF6GQvrMrjacQX6ees6" -isVerified: true }现在,如果您使用该 ULID 来检索您的用户,它也将起作用!
如果您检查该 UUID,您会发现返回的对象已将该 uuid 转换为基数 32:
最后,您可以通过将其转换为 refc4122 来获取存储的 uuid,如下所示:
我不确定为什么原则不只存储 ULID,但它当前的行为并没有阻止您在项目中使用 ULID。 希望这有帮助!