Gestern habe ich versucht, das zu tun, was Symfony in einem Blog-Beitrag gefordert hat (https://symfony.com/blog/new-in-symfony-5-2-doctrine-types-for-uuid-and-ulid), aber es ist mir nicht gelungen. Ich möchte ULIDs (im Format „TTTTTTTTTTRRRRRRRRRRRR“) in der Datenbank speichern, weil sie nicht nur sortierbar sind, sondern auch einen Zeitstempel enthalten, der perfekt für meine Anwendung ist. Wenn ich dem Attribut jedoch sage, dass es „type=ulid“ ist, wird es in der Datenbank als UUID gespeichert (Format: „xxxxxxxx-xxxx-Mxxx-Nxxx-xxxxxxxxxxxx“).
Ich habe einen halben Tag lang debuggt und mich darüber so geärgert, dass ich von vorne angefangen habe und das Problem immer noch besteht.
Was habe ich falsch gemacht?
(Wenn Sie möchten, fahren Sie mit der ULID-Kopfzeile fort. Das Folgende sieht vielleicht lang aus, aber 50 % davon sind nur die Grundlagen)
Dinge, die ich immer wieder mache. Entnommen von https://symfony.com/doc/5.4/setup.html:
stat shyt # 不存在
composer 创建项目 symfony/sculpture:5.4.* shyt
cd shyt;作曲家需要 webapp
bin/console about
Zeigt Symfony-Version 5.4.10 und PHP 7.4Entnommen von https://symfony.com/doc/5.4/doctrine.html:
composer 需要 symfony/orm-pack
composer 需要 --dev symfony/maker-bundle
docker-compose up -d
Fehler: Im dem Netzwerk zugewiesenen Standardadresspool wurde kein verfügbarer, nicht überlappender IPv4-Adresspool gefunden
Also habe ich einige Zeilen in die Datei docker-compose.override.yml eingefügt:
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
(albern, aber wie dokumentiert) Datenbank-App für Verbindung mit dem Namen „Standard“ kann nicht erstellt werden Beim Ausführen der Abfrage ist eine Ausnahme aufgetreten: SQLSTATE[42P04]: Doppelte Datenbank: 7 Fehler: Datenbank „app“ existiert bereits
Nun ja. Docker macht das bereits.
make:entity
Verzögert, bis wir die ULID-Funktionalität haben. Wir haben uns an https://symfony.com/doc/5.4/components/uid.html orientiert (insbesondere an den ULID-Teil):
composer 需要 symfony/uid
bin/console make:entity Product
Sieht fast genauso aus wie in der Dokumentation, außer dass es ein zusätzliches Feld (Primärschlüssel, eine Ganzzahl) und einige Getter/Setter enthält.
Zwischendurch erstellen wir programmgesteuert Datenbankeinträge mithilfe von Tests:
composer 需要 phpunit
Datenbankeinträge programmgesteuert erstellenbin/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'
Nur um sicherzugehenbin/phpunit
bin/console --env=测试主义:query:sql 'SELECT * FROM 产品'
UUID anzeigen, nicht ULID.
ULID statt UUID in der Datenbank anzeigen
Bereinigen Sie es zuerst und führen Sie dann das unter https://symfony.com/doc/5.4/components/uid.html#ulids gezeigte Beispiel aus:
rm 迁移/*
Von vorne beginnenbin/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; } // ... }
(Im Beispiel in der Dokumentation fehlt die Repository-Zeile)
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
(Es ist in Ordnung, riskant zu sein)bin/console --env=测试主义:query:sql 'SELECT * FROM 产品'
Verwenden Sie erneut UUID anstelle von ULID
Datenbank zeigt UUID statt ULID an
有点晚了,但对于面临这个问题的人来说,我也有显示 UUID 而不是 ULID 的数据库,这似乎是学说中的预期行为,因为您可以互换使用 UUID/ULID,这意味着即使您将 UUID 存储在数据库,但您的实体映射到 ULID,从数据库检索对象时您将拥有 ULID,您也可以使用 ULID 或 UUID 检索相同的对象。
例如,我有一个用户实体,其标识符具有 ULID,因此存储的对象将具有如下 uuid:
如果我使用该 UUID 检索我的用户,我将得到:
现在,如果您使用该 ULID 来检索您的用户,它也将起作用!
如果您检查该 UUID,您会发现返回的对象已将该 uuid 转换为基数 32:
最后,您可以通过将其转换为 refc4122 来获取存储的 uuid,如下所示:
我不确定为什么原则不只存储 ULID,但它当前的行为并没有阻止您在项目中使用 ULID。 希望这有帮助!