suchen

Heim  >  Fragen und Antworten  >  Hauptteil

ULID wurde fälschlicherweise als UUID in der Datenbank gespeichert (Vanilla Symfony-Anwendung)

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)

Symphonie

Dinge, die ich immer wieder mache. Entnommen von https://symfony.com/doc/5.4/setup.html:

  1. stat shyt # 不存在
  2. composer 创建项目 symfony/sculpture:5.4.* shyt
  3. cd shyt;作曲家需要 webapp
  4. Möchten Sie die Docker-Konfiguration in das Rezept einbeziehen? Ja (Standard)
  5. bin/console about Zeigt Symfony-Version 5.4.10 und PHP 7.4

ORM

Entnommen von https://symfony.com/doc/5.4/doctrine.html:

  1. composer 需要 symfony/orm-pack
  2. composer 需要 --dev symfony/maker-bundle
  3. 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
  1. Setzen Sie DATABASE_URL in „.env“ für Host „10.1.2.3“ ein
  2. 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.

  1. make:entity Verzögert, bis wir die ULID-Funktionalität haben.

ULID

Wir haben uns an https://symfony.com/doc/5.4/components/uid.html orientiert (insbesondere an den ULID-Teil):

  1. composer 需要 symfony/uid
  2. bin/console make:entity Product
  1. Überprüfen Sie die Produktentität

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.

  1. bin/console make:migration

Testen von ULID-Entitäten

Zwischendurch erstellen wir programmgesteuert Datenbankeinträge mithilfe von Tests:

  1. composer 需要 phpunit Datenbankeinträge programmgesteuert erstellen
  2. bin/console --env=测试主义:migrations:migrate
  3. bin/console --env=测试主义:数据库:create
  4. Die Datei „tests/FooTest.php“ enthält:
<?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' Nur um sicherzugehen
  2. bin/phpunit
  3. bin/console --env=测试主义:query:sql 'SELECT * FROM 产品'

UUID anzeigen, nicht ULID.

ULID statt UUID in der Datenbank anzeigen

Verwenden Sie ULID als Primärschlüssel

Bereinigen Sie es zuerst und führen Sie dann das unter https://symfony.com/doc/5.4/components/uid.html#ulids gezeigte Beispiel aus:

  1. rm 迁移/* Von vorne beginnen
  2. bin/console --env=测试主义:database:drop --force
  3. bin/console --env=测试主义:数据库:create
  4. bin/控制台主义:数据库:drop --force
  5. bin/console --env=测试主义:数据库:create
  6. Bearbeiten Sie „src/Entity/Product.php“, um nur die zweite ULID aus der Dokumentation einzuschließen. Beispiel:
<?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)

  1. bin/console make:migration
  2. bin/console --env=测试主义:migrations:migrate
  3. Testen ist jetzt noch einfacher:
public function testFoo(): void
    {
        self::getContainer()->get(ProductRepository::class)
            ->add(new Product());

        self::getContainer()->get('doctrine.orm.entity_manager')
            ->flush();
    }
  1. bin/phpunit(Es ist in Ordnung, riskant zu sein)
  2. bin/console --env=测试主义:query:sql 'SELECT * FROM 产品'

Verwenden Sie erneut UUID anstelle von ULID

Datenbank zeigt UUID statt ULID an

P粉381463780P粉381463780333 Tage vor610

Antworte allen(1)Ich werde antworten

  • P粉377412096

    P粉3774120962023-12-17 00:06:49

    有点晚了,但对于面临这个问题的人来说,我也有显示 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: "$2y$13$/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。 希望这有帮助!

    Antwort
    0
  • StornierenAntwort