10

我正在将 Symfony2 与 Doctrine 一起使用,并且我正在使用 Alice Fixture 包来生成我的测试装置。

在一种情况下,我需要为特定测试创建一个 id 为 148 的夹具。我们所有的 id 都配置为 auto_increment,所以我目前正在创建 147 个虚拟记录,只是为了创建我需要的那个。

我希望使用这个定义来强制将 id 设置为 148:

 invoiceClassNoClass (extends invoiceClass):
    id: 148
    sortOrder: 1
    label: 'No Class'

不幸的是,这不起作用。从谷歌搜索中,我读到了一条简短的评论,指出我首先需要向我的实体添加一个 setId 方法。我试过了,但没有任何区别。实际上,如果不需要,我不想添加为 setId 方法,因为它违反了我们从不允许设置 id 的完整性规则。

也许有可以使用的反射类?也许这是爱丽丝内置的,我不知道?

4

3 回答 3

10

如果您希望学说为自动增量 ID 保存某个值,那么您必须在学说元数据中停用自动增量。看

使用“AUTO”策略时使用 Doctrine 显式设置 Id

$this->em->persist($entity);

$metadata = $this->em->getClassMetaData(get_class($entity));
$metadata->setIdGenerator(new \Doctrine\ORM\Id\AssignedGenerator());
于 2016-04-30T11:31:04.023 回答
9

更新:在对该主题进行进一步研究后,我意识到在固定装置中硬编码 id 有其自身的问题,通常不是一个好主意。相反,当您需要检查特定记录时,最好通过 yml 文件中的引用来获取固定装置。


由于问题是关于 Alice 固定装置包的,我发现以下内容对我有用:

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()方法。

于 2016-07-29T11:27:15.923 回答
6

我也遇到了这个问题,因为我希望每次运行时都有一些 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);
}

$metadata为您希望拥有自定义 id ( App::class)的所有类执行-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'

证明:

在此处输入图像描述

于 2017-03-30T13:44:54.033 回答