昨天我嘗試做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。 希望有幫助!