ULID 在資料庫中錯誤地儲存為 UUID(vanilla symfony 應用程式)
P粉381463780
P粉381463780 2023-12-16 08:43:42
0
1
559

昨天我嘗試做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:

  1. stat shyt # 不存在
  2. composer 建立專案 symfony/sculpture:5.4.* shyt
  3. cd shyt;作曲家需要 webapp
  4. 您想包含食譜中的 Docker 配置嗎?是(預設)
  5. bin/console about 顯示 Symfony 版本 5.4.10 和 PHP 7.4

ORM

取自https://symfony.com/doc/5.4/doctrine.html:

  1. composer 需要 symfony/orm-pack
  2. composer 需要 --dev symfony/maker-bundle
  3. #
  4. 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
  1. 在「.env」中為主機「10.1.2.3」設定 DATABASE_URL
  2. bin/console 學說:資料庫:create(很愚蠢,但如文件所述)

無法為名為default的連線建立資料庫“app” 執行查詢時發生例外狀況:SQLSTATE[42P04]:重複資料庫:7錯誤:資料庫「app」已存在

嗯,是的。 Docker 已經做到了這一點。

  1. make:entity 被推遲,直到我們擁有 ULID 功能。

ULID

我們已經傾向於 https://symfony.com/doc/5.4/components/uid.html (尤其是 ULID 部分):

  1. composer 需要 symfony/uid
  2. #
  3. bin/console make:entity Product
  4. #
  • 「someProperty」當「ulid」不可為空
  1. 檢查產品實體

看起來幾乎與文件中的一樣,只是它有一個附加欄位(主鍵,一個整數)和一些 getter/setter。

  1. bin/console make:migration

測試 ULID 實體

在這之間,我們使用測試以程式設計方式建立資料庫條目:###
  1. composer 需要 phpunit 以程式設計方式建立資料庫條目
  2. bin/console --env=測試主義:migrations:migrate
  3. #
  4. bin/console --env=測試主義:資料庫:create
  5. 檔案「tests/FooTest.php」包含:
<?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();
    }
}
  1. bin/console --env=test 主義:query:sql 'TRUNCATE Product' 只是為了確定
  2. bin/phpunit
  3. #
  4. bin/console --env=測試主義:query:sql 'SELECT * FROM 產品'

顯示 UUID,而不是 ULID。

在資料庫中顯示 ULID 而不是 UUID

使用 ULID 作為主鍵

先清理一下,然後執行 https://symfony.com/doc/5.4/components/uid.html#ulids 中所示的範例:

  1. rm 遷移/* 重新開始
  2. bin/console --env=測試主義:database:drop --force
  3. #
  4. bin/console --env=測試主義:資料庫:create
  5. bin/控制台主義:資料庫:drop --force
  6. #
  7. bin/console --env=測試主義:資料庫:create
  8. 編輯「src/Entity/Product.php」以僅包含文件中的第二個 ULID 範例:
<?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;
    }

    // ...

}

(文件中的範例缺少儲存庫行)

  1. bin/console make:migration
  2. #
  3. bin/console --env=測試主義:migrations:migrate
  4. #
  5. 測試現在更簡單了:
public function testFoo(): void
    {
        self::getContainer()->get(ProductRepository::class)
            ->add(new Product());

        self::getContainer()->get('doctrine.orm.entity_manager')
            ->flush();
    }
  1. bin/phpunit(有風險也可以)
  2. bin/console --env=測試主義:query:sql 'SELECT * FROM 產品'

再次使用 UUID 而不是 ULID

#

資料庫顯示 UUID 而不是 ULID

#
P粉381463780
P粉381463780

全部回覆(1)
P粉377412096

有點晚了,但對於面臨這個問題的人來說,我也有顯示UUID 而不是ULID 的資料庫,這似乎是學說中的預期行為,因為您可以互換使用UUID/ULID,這意味著即使您將UUID 儲存在資料庫,但您的實體對應到ULID,從資料庫擷取物件時您將擁有ULID,您也可以使用ULID 或UUID 擷取相同的物件。

例如,我有一個使用者實體,其識別碼具有 ULID,因此儲存的物件將具有以下 uuid:

018477e6-eebc-164c-12e3-22ca8f1a88f3    myemail@mail.com    []

如果我使用該 UUID 檢索我的用戶,我將得到:

App\Entity\User {#430 ▼
 -id: "01GHVYDVNW2S615RS2SA7HN27K"
 -email: "myemail@mail.com"
 -roles: []
 #createdAt: DateTime @1668458933 {#423 ▶}
 #updatedAt: DateTime @1668458998 {#428 ▶}
 -password: "y$/2i9Ovc2lCQBRfSVgsnmoul1FhF.Kyki3irF6GQvrMrjacQX6ees6"
 -isVerified: true
}

現在,如果您使用該 ULID 來檢索您的用戶,它也將起作用!

如果您檢查該 UUID,您會發現傳回的物件已將該 uuid 轉換為基底數 32:

bash-5.1$ bin/console uuid:inspect 018477e6-eebc-164c-12e3-22ca8f1a88f3
----------------------- --------------------------------------
Label                   Value
----------------------- --------------------------------------
Version                 1                                     
  toRfc4122 (canonical)   018477e6-eebc-164c-12e3-22ca8f1a88f3  
  toBase58                1BsMRvKcgozP4Kw2m4Fb1C                
  toBase32                01GHVYDVNW2S615RS2SA7HN27K
----------------------- --------------------------------------

最後,您可以透過將其轉換為 refc4122 來取得儲存的 uuid,如下所示:

bin/console ulid:inspect 01GHVYDVNW2S615RS2SA7HN27K
---------------------- --------------------------------------
Label                  Value
---------------------- --------------------------------------
toBase32 (canonical)   01GHVYDVNW2S615RS2SA7HN27K
toBase58               1BsMRvKcgozP4Kw2m4Fb1C
toRfc4122              018477e6-eebc-164c-12e3-22ca8f1a88f3
---------------------- --------------------------------------
Time                   2022-11-14 20:48:53.948 UTC
---------------------- --------------------------------------

我不確定為什麼原則不只儲存 ULID,但它目前的行為並沒有阻止您在專案中使用 ULID。 希望有幫助!

熱門教學
更多>
最新下載
更多>
網站特效
網站源碼
網站素材
前端模板
關於我們 免責聲明 Sitemap
PHP中文網:公益線上PHP培訓,幫助PHP學習者快速成長!