Maison  >  Questions et réponses  >  le corps du texte

ULID incorrectement stocké en tant qu'UUID dans la base de données (application Vanilla Symfony)

Hier, j'ai essayé de faire ce que Symfony a crié dans un article de blog (https://symfony.com/blog/new-in-symfony-5-2-doctrine-types-for-uuid-and-ulid) mais j'ai échoué. Je souhaite stocker les ULID (au format "TTTTTTTTTTRRRRRRRRRRRR") dans la base de données car non seulement ils sont triables, mais ils contiennent également un horodatage parfait pour mon application. Cependant, lorsque je dis à l'attribut d'être "type=ulid", il est stocké dans la base de données sous forme d'UUID (format : "xxxxxxx-xxxx-Mxxx-Nxxx-xxxxxxxxxxxx").

J'ai débogué pendant une demi-journée et j'ai été tellement ennuyé par cela que j'ai recommencé à zéro et le problème existe toujours.

Où est-ce que je me suis trompé ?

(passez à l'en-tête ULID si vous le souhaitez, ce qui suit peut paraître long mais 50 % ne sont que des bases)

Symphonie

Choses que je fais encore et encore Tiré de https://symfony.com/doc/5.4/setup.html :

  1. stat shyt # 不存在
  2. composer 创建项目 symfony/sculpture:5.4.* shyt
  3. cd shyt;作曲家需要 webapp
  4. Voulez-vous inclure la configuration Docker dans la recette ? Oui (par défaut)
  5. bin/console about Affichage de Symfony version 5.4.10 et PHP 7.4

ORM

Tiré de https://symfony.com/doc/5.4/doctrine.html :

  1. composer 需要 symfony/orm-pack
  2. composer 需要 --dev symfony/maker-bundle
  3. docker-compose up -d

Erreur : aucun pool d'adresses IPv4 disponible et sans chevauchement trouvé dans le pool d'adresses par défaut attribué au réseau

J'ai donc ajouté quelques lignes dans le fichier 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. Définissez DATABASE_URL dans ".env" pour l'hôte "10.1.2.3"
  2. bin/console 学说:数据库:create (idiot, mais comme documenté)

Impossible de créer une « application » de base de données pour la connexion nommée par défaut Une exception s'est produite lors de l'exécution de la requête : SQLSTATE[42P04] : base de données en double : 7 Erreur : la base de données "app" existe déjà

Eh bien, oui. Docker le fait déjà.

  1. make:entity Retardé jusqu'à ce que nous ayons la fonctionnalité ULID.

ULID

Nous avons penché vers https://symfony.com/doc/5.4/components/uid.html (surtout la partie ULID) :

  1. composer 需要 symfony/uid
  2. bin/console make:entity Product
  1. Vérifier l'entité du produit

L'apparence est presque la même que dans la documentation, sauf qu'elle comporte un champ supplémentaire (clé primaire, un entier) et quelques getters/setters.

  1. marque bin/console:migration

Test des entités ULID

Entre les deux, nous créons des entrées de base de données par programmation à l'aide de tests :

  1. composer 需要 phpunit Créer des entrées de base de données par programmation
  2. bin/console --env=测试主义:migrations:migrate
  3. bin/console --env=测试主义:数据库:create
  4. Le fichier "tests/FooTest.php" contient :
<?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' Juste pour être sûr
  2. bin/phpunit
  3. bin/console --env=测试主义:query:sql 'SELECT * FROM 产品'

Afficher l'UUID, pas l'ULID.

Afficher l'ULID au lieu de l'UUID dans la base de données

Utilisez ULID comme clé primaire

Nettoyez-le d'abord, puis exécutez l'exemple présenté sur https://symfony.com/doc/5.4/components/uid.html#ulids :

  1. rm 迁移/* Recommencez
  2. bin/console --env=测试主义:database:drop --force
  3. bin/console --env=测试主义:数据库:create
  4. bin/控制台主义:数据库:drop --force
  5. bin/console --env=测试主义:数据库:create
  6. Modifiez "src/Entity/Product.php" pour inclure uniquement le deuxième ULID de la documentation Exemple :
<?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;
    }

    // ...

}

(Il manque la ligne du référentiel dans l'exemple dans la documentation)

  1. bin/console make:migration
  2. bin/console --env=测试主义:migrations:migrate
  3. Les tests sont désormais encore plus simples :
public function testFoo(): void
    {
        self::getContainer()->get(ProductRepository::class)
            ->add(new Product());

        self::getContainer()->get('doctrine.orm.entity_manager')
            ->flush();
    }
  1. bin/phpunit(C'est normal de prendre des risques)
  2. bin/console --env=测试主义:query:sql 'SELECT * FROM 产品'

Utilisez à nouveau l'UUID au lieu de l'ULID

La base de données affiche l'UUID au lieu de l'ULID

P粉381463780P粉381463780282 Il y a quelques jours566

répondre à tous(1)je répondrai

  • P粉377412096

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

    Un peu tard, mais pour tous ceux qui sont confrontés à ce problème, j'ai aussi des bases de données qui affichent les UUID au lieu des ULID, ce qui semble être le comportement attendu dans Doctrine puisque vous pouvez utiliser les UUID/ULID de manière interchangeable, ce qui signifie que même si vous le souhaitez, l'UUID est stocké dans base de données mais votre entité est mappée à ULID, lors de la récupération d'un objet de la base de données, vous aurez ULID, vous pouvez également récupérer le même objet en utilisant ULID ou UUID.

    Par exemple, j'ai une entité utilisateur dont l'identifiant a un ULID, donc l'objet stocké aura un uuid comme ceci :

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

    Si je récupère mon utilisateur en utilisant cet UUID, j'obtiens :

    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
    }

    Maintenant, si vous utilisez cet ULID pour récupérer votre utilisateur, cela fonctionnera aussi !

    Si vous inspectez l'UUID, vous verrez que l'uuid de l'objet renvoyé a été converti en base 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
    ----------------------- --------------------------------------

    Enfin, vous pouvez obtenir l'uuid stocké en le convertissant en refc4122 comme ceci :

    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
    ---------------------- --------------------------------------

    Je ne sais pas pourquoi Principe ne stocke pas uniquement les ULID, mais son comportement actuel ne vous empêche pas d'utiliser les ULID dans votre projet. J'espère que cela t'aides!

    répondre
    0
  • Annulerrépondre