昨天我尝试做 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.* shyt
cd shyt;作曲家需要 webapp
bin/console about
显示 Symfony 版本 5.4.10 和 PHP 7.4取自https://symfony.com/doc/5.4/doctrine.html:
composer 需要 symfony/orm-pack
composer 需要 --dev symfony/maker-bundle
docker-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/uid
bin/console make:entity Product
看起来几乎与文档中的一样,只是它有一个附加字段(主键,一个整数)和一些 getter/setter。
在这之间,我们使用测试以编程方式创建数据库条目:
composer 需要 phpunit
以编程方式创建数据库条目bin/console --env=测试主义:migrations:migrate
bin/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/phpunit
bin/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 --force
bin/console --env=测试主义:数据库:create
bin/控制台主义:数据库:drop --force
bin/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:migration
bin/console --env=测试主义:migrations:migrate
public 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
有点晚了,但对于面临这个问题的人来说,我也有显示 UUID 而不是 ULID 的数据库,这似乎是学说中的预期行为,因为您可以互换使用 UUID/ULID,这意味着即使您将 UUID 存储在数据库,但您的实体映射到 ULID,从数据库检索对象时您将拥有 ULID,您也可以使用 ULID 或 UUID 检索相同的对象。
例如,我有一个用户实体,其标识符具有 ULID,因此存储的对象将具有如下 uuid:
如果我使用该 UUID 检索我的用户,我将得到:
现在,如果您使用该 ULID 来检索您的用户,它也将起作用!
如果您检查该 UUID,您会发现返回的对象已将该 uuid 转换为基数 32:
最后,您可以通过将其转换为 refc4122 来获取存储的 uuid,如下所示:
我不确定为什么原则不只存储 ULID,但它当前的行为并没有阻止您在项目中使用 ULID。 希望这有帮助!