Semalam saya cuba melakukan apa yang Symfony laungkan dalam beberapa catatan blog (https://symfony.com/blog/new-in-symfony-5-2-doctrine-types-for-uuid-and-ulid) tetapi gagal . Saya ingin menyimpan ULID (dalam format "TTTTTTTTTTRRRRRRRRRR") dalam pangkalan data kerana ia bukan sahaja boleh diisih, tetapi ia juga mengandungi cap waktu yang sesuai untuk aplikasi saya. Walau bagaimanapun, apabila saya memberitahu atribut itu sebagai "type=ulid", ia disimpan dalam pangkalan data sebagai UUID (format: "xxxxxxxx-xxxx-Mxxx-Nxxx-xxxxxxxxxxxx").
Saya debug selama setengah hari dan sangat jengkel dengan ini sehingga saya bermula dari awal dan masalah itu masih wujud.
Di mana silap saya?
(langkau ke pengepala ULID jika anda mahu, yang berikut mungkin kelihatan panjang tetapi 50% daripadanya hanyalah asas)
Perkara yang saya lakukan berulang kali Diambil daripada https://symfony.com/doc/5.4/setup.html:
stat shyt # 不存在
composer 创建项目 symfony/sculpture:5.4.* shyt
cd shyt;作曲家需要 webapp
bin/console about
Menunjukkan Symfony versi 5.4.10 dan PHP 7.4Diambil daripada https://symfony.com/doc/5.4/doctrine.html:
composer 需要 symfony/orm-pack
composer 需要 --dev symfony/maker-bundle
docker-compose up -d
Ralat: Tiada kumpulan alamat IPv4 yang tersedia dan tidak bertindih ditemui dalam kumpulan alamat lalai yang diberikan kepada rangkaian
Jadi saya menambah beberapa baris dalam fail 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
(bodoh, tetapi seperti yang didokumenkan) Tidak boleh mencipta 'apl' pangkalan data untuk sambungan bernama lalai Pengecualian berlaku semasa melaksanakan pertanyaan: SQLSTATE[42P04]: Pangkalan data pendua: 7 Ralat: "apl" pangkalan data sudah wujud
Nah, ya. Docker sudah melakukan ini.
make:entity
Ditangguh sehingga kami mempunyai fungsi ULID. Kami telah condong ke https://symfony.com/doc/5.4/components/uid.html (terutama bahagian ULID):
composer 需要 symfony/uid
bin/console make:entity Product
Kelihatan hampir sama seperti dalam dokumentasi, kecuali ia mempunyai medan tambahan (kunci utama, integer) dan beberapa getter/setter.
Di antaranya, kami mencipta entri pangkalan data secara pemrograman menggunakan ujian:
composer 需要 phpunit
Cipta entri pangkalan data secara pengaturcaraanbin/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'
Hanya untuk memastikanbin/phpunit
bin/console --env=测试主义:query:sql 'SELECT * FROM 产品'
Tunjukkan UUID, bukan ULID.
Tunjukkan ULID dan bukannya UUID dalam pangkalan data
Mula-mula bersihkannya dan kemudian laksanakan contoh yang ditunjukkan di https://symfony.com/doc/5.4/components/uid.html#ulids:
rm 迁移/*
Mulakan semulabin/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; } // ... }
(Contoh dalam dokumentasi tiada baris repositori)
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
(Berisiko tidak mengapa)bin/console --env=测试主义:query:sql 'SELECT * FROM 产品'
Guna UUID dan bukannya ULID lagi
Pangkalan data menunjukkan UUID dan bukannya ULID
Agak lewat tetapi bagi sesiapa yang menghadapi isu ini, saya juga mempunyai pangkalan data yang menunjukkan UUID dan bukannya ULID, yang nampaknya merupakan tingkah laku yang diharapkan dalam Doktrin kerana anda boleh menggunakan UUID/ULID secara bergantian, bermakna walaupun anda akan UUID disimpan dalam pangkalan data tetapi entiti anda dipetakan ke ULID, apabila mendapatkan semula objek daripada pangkalan data anda akan mempunyai ULID, anda juga boleh mendapatkan objek yang sama menggunakan ULID atau UUID.
Sebagai contoh, saya mempunyai entiti pengguna yang pengecamnya mempunyai ULID, jadi objek yang disimpan akan mempunyai uuid seperti ini:
Jika saya mendapatkan semula pengguna saya menggunakan UUID itu, saya mendapat:
Kini, jika anda menggunakan ULID itu untuk mendapatkan semula pengguna anda, ia juga akan berfungsi!
Jika anda memeriksa UUID, anda akan melihat bahawa objek yang dikembalikan mempunyai uuid yang ditukar kepada asas 32:
Akhir sekali, anda boleh mendapatkan uuid yang disimpan dengan menukarnya kepada refc4122 seperti ini:
Saya tidak pasti mengapa Prinsip tidak hanya menyimpan ULID, tetapi tingkah laku semasanya tidak menghalang anda daripada menggunakan ULID dalam projek anda. Harap ini membantu!