我可以用 Alice Fixtures 覆盖自动递增 ID 吗?
Can I override auto increment ID with Alice Fixtures?
我正在使用 Symfony2 和 Doctrine,我正在使用 Alice Fixture 包来生成我的测试用具。
在一种情况下,我需要为特定测试创建一个 ID 为 148 的夹具。我们所有的 ID 都配置为 auto_increment,所以我目前正在创建 147 个虚拟记录,只是为了创建我需要的那个。
我希望使用这个定义来强制将 id 设置为 148:
invoiceClassNoClass (extends invoiceClass):
id: 148
sortOrder: 1
label: 'No Class'
不幸的是,这不起作用。从 google 搜索中,我读到一条简短的评论,指出我首先需要向我的实体添加一个 setId 方法。我试过了,但没有什么不同。实际上,如果不需要的话,我不想添加 setId 方法,因为它违反了我们从不允许设置 id 的完整性规则。
也许有可以使用的反射class?也许这是爱丽丝内置的,我不知道?
如果你想让 doctrine 为自动递增 Id 保存特定值,那么你必须在 doctrine 元数据中停用自动递增。参见
Explicitly set Id with Doctrine when using "AUTO" strategy
$this->em->persist($entity);
$metadata = $this->em->getClassMetaData(get_class($entity));
$metadata->setIdGenerator(new \Doctrine\ORM\Id\AssignedGenerator());
更新:
在对该主题进行进一步研究后,我意识到在固定装置中硬编码 id 有其自身的问题,通常不是一个好主意。相反,当您需要检查特定记录时,最好通过它们在 yml 文件中的引用来获取固定装置。
由于问题是关于 Alice fixtures bundle,我发现以下内容对我有用:
protected $idGeneratorTypes = [];
protected function allowFixedIdsFor(array $entityClasses)
{
$em = $this->getContainer()->get('doctrine')->getManager();
foreach ($entityClasses as $entityClass) {
$metadata = $em->getClassMetadata($entityClass);
$this->idGeneratorTypes[$entityClass] = $metadata->generatorType;
$metadata->setIdGeneratorType(\Doctrine\ORM\Mapping\ClassMetadata::GENERATOR_TYPE_NONE);
}
}
protected function recoverIdGenerators()
{
$em = $this->getContainer()->get('doctrine')->getManager();
foreach ($this->idGeneratorTypes as $entityClass => $idGeneratorType) {
$metadata = $em->getClassMetadata($entityClass);
$metadata->setIdGeneratorType($idGeneratorType);
}
}
然后在测试的setUp()方法中,我有
$this->allowFixedIdsFor([
MyEntity::class,
]);
$this->loadFixtureFiles([
'./tests/DataFixtures/ORM/my_entities.yml',
]);
$this->recoverIdGenerators();
看起来您的实体中似乎不需要 setId() 方法。
我也 运行 解决了这个问题,因为我希望某些 ID 每个 运行 都相同,因为我想使用 UUID
策略在我的调试应用程序中引用它们。
我做了什么:
1) 写了一个包装 hautelook:fixtures:load
:
的命令
protected function execute(InputInterface $input, OutputInterface $output)
{
$container = $this->getContainer();
$entityManager = $container->get('doctrine.orm.default_entity_manager');
$metadata = $entityManager->getClassMetaData(App::class);
$metadata->setIdGeneratorType(\Doctrine\ORM\Mapping\ClassMetadata::GENERATOR_TYPE_NONE);
$metadata->setIdGenerator(new \Doctrine\ORM\Id\AssignedGenerator());
$application = new Application($kernel);
$application->setAutoExit(false);
$this->loadFixtures($application, $output);
}
为所有 类 想要自定义 ID (App::class
) 的人做 $metadata
-stuff。
protected function loadFixtures(Application $application, OutputInterface $output)
{
$loadFixturesInput = new ArrayInput(array(
'command' => 'hautelook:fixtures:load',
'--no-interaction' => 'true',
'--verbose' => '3'
));
$application->run($loadFixturesInput, $output);
}
2) 我创建了一个模板来生成像学说那样的 id
。
id (template):
id (unique): '<uuid()>'
3) 在我的自定义实体夹具中,现在我可以执行以下操作:
app_custom (extends id):
id: 'whatever-i-want'
title: 'My custom entity'
4) 如果我 不想 使用自定义 ID,我只是不覆盖 id
字段:
app_another (extends id):
title: 'Just another app with an id I do not care about'
证明:
我正在使用 Symfony2 和 Doctrine,我正在使用 Alice Fixture 包来生成我的测试用具。
在一种情况下,我需要为特定测试创建一个 ID 为 148 的夹具。我们所有的 ID 都配置为 auto_increment,所以我目前正在创建 147 个虚拟记录,只是为了创建我需要的那个。
我希望使用这个定义来强制将 id 设置为 148:
invoiceClassNoClass (extends invoiceClass):
id: 148
sortOrder: 1
label: 'No Class'
不幸的是,这不起作用。从 google 搜索中,我读到一条简短的评论,指出我首先需要向我的实体添加一个 setId 方法。我试过了,但没有什么不同。实际上,如果不需要的话,我不想添加 setId 方法,因为它违反了我们从不允许设置 id 的完整性规则。
也许有可以使用的反射class?也许这是爱丽丝内置的,我不知道?
如果你想让 doctrine 为自动递增 Id 保存特定值,那么你必须在 doctrine 元数据中停用自动递增。参见
Explicitly set Id with Doctrine when using "AUTO" strategy
$this->em->persist($entity);
$metadata = $this->em->getClassMetaData(get_class($entity));
$metadata->setIdGenerator(new \Doctrine\ORM\Id\AssignedGenerator());
更新: 在对该主题进行进一步研究后,我意识到在固定装置中硬编码 id 有其自身的问题,通常不是一个好主意。相反,当您需要检查特定记录时,最好通过它们在 yml 文件中的引用来获取固定装置。
由于问题是关于 Alice fixtures bundle,我发现以下内容对我有用:
protected $idGeneratorTypes = [];
protected function allowFixedIdsFor(array $entityClasses)
{
$em = $this->getContainer()->get('doctrine')->getManager();
foreach ($entityClasses as $entityClass) {
$metadata = $em->getClassMetadata($entityClass);
$this->idGeneratorTypes[$entityClass] = $metadata->generatorType;
$metadata->setIdGeneratorType(\Doctrine\ORM\Mapping\ClassMetadata::GENERATOR_TYPE_NONE);
}
}
protected function recoverIdGenerators()
{
$em = $this->getContainer()->get('doctrine')->getManager();
foreach ($this->idGeneratorTypes as $entityClass => $idGeneratorType) {
$metadata = $em->getClassMetadata($entityClass);
$metadata->setIdGeneratorType($idGeneratorType);
}
}
然后在测试的setUp()方法中,我有
$this->allowFixedIdsFor([
MyEntity::class,
]);
$this->loadFixtureFiles([
'./tests/DataFixtures/ORM/my_entities.yml',
]);
$this->recoverIdGenerators();
看起来您的实体中似乎不需要 setId() 方法。
我也 运行 解决了这个问题,因为我希望某些 ID 每个 运行 都相同,因为我想使用 UUID
策略在我的调试应用程序中引用它们。
我做了什么:
1) 写了一个包装 hautelook:fixtures:load
:
protected function execute(InputInterface $input, OutputInterface $output)
{
$container = $this->getContainer();
$entityManager = $container->get('doctrine.orm.default_entity_manager');
$metadata = $entityManager->getClassMetaData(App::class);
$metadata->setIdGeneratorType(\Doctrine\ORM\Mapping\ClassMetadata::GENERATOR_TYPE_NONE);
$metadata->setIdGenerator(new \Doctrine\ORM\Id\AssignedGenerator());
$application = new Application($kernel);
$application->setAutoExit(false);
$this->loadFixtures($application, $output);
}
为所有 类 想要自定义 ID (App::class
) 的人做 $metadata
-stuff。
protected function loadFixtures(Application $application, OutputInterface $output)
{
$loadFixturesInput = new ArrayInput(array(
'command' => 'hautelook:fixtures:load',
'--no-interaction' => 'true',
'--verbose' => '3'
));
$application->run($loadFixturesInput, $output);
}
2) 我创建了一个模板来生成像学说那样的 id
。
id (template):
id (unique): '<uuid()>'
3) 在我的自定义实体夹具中,现在我可以执行以下操作:
app_custom (extends id):
id: 'whatever-i-want'
title: 'My custom entity'
4) 如果我 不想 使用自定义 ID,我只是不覆盖 id
字段:
app_another (extends id):
title: 'Just another app with an id I do not care about'
证明: