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)
Choses que je fais encore et encore Tiré de https://symfony.com/doc/5.4/setup.html :
stat shyt # 不存在
composer 创建项目 symfony/sculpture:5.4.* shyt
cd shyt;作曲家需要 webapp
bin/console about
Affichage de Symfony version 5.4.10 et PHP 7.4Tiré de https://symfony.com/doc/5.4/doctrine.html :
composer 需要 symfony/orm-pack
composer 需要 --dev symfony/maker-bundle
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
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à.
make:entity
Retardé jusqu'à ce que nous ayons la fonctionnalité ULID. Nous avons penché vers https://symfony.com/doc/5.4/components/uid.html (surtout la partie ULID) :
composer 需要 symfony/uid
bin/console make:entity Product
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.
Entre les deux, nous créons des entrées de base de données par programmation à l'aide de tests :
composer 需要 phpunit
Créer des entrées de base de données par programmationbin/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'
Juste pour être sûrbin/phpunit
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
Nettoyez-le d'abord, puis exécutez l'exemple présenté sur https://symfony.com/doc/5.4/components/uid.html#ulids :
rm 迁移/*
Recommencezbin/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; } // ... }
(Il manque la ligne du référentiel dans l'exemple dans la documentation)
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
(C'est normal de prendre des risques)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
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 :
Si je récupère mon utilisateur en utilisant cet UUID, j'obtiens :
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 :
Enfin, vous pouvez obtenir l'uuid stocké en le convertissant en refc4122 comme ceci :
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!