Can I override auto increment ID with Alice Fixtures?
If you want doctrine to save a certain value for an auto increment Id, then you have to deactivate auto increment in doctrine metadata. See
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());
UPDATE:After further research on the subject, I realised that hardcoding ids in fixtures comes with its own problems and is generally not a good idea. Instead, it's better to get fixtures by their reference in the yml file when you need to check for a specific record.
Since the question is about the Alice fixtures bundle, I found the following to work for me:
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); }}
Then in the test's setUp() method, I have
$this->allowFixedIdsFor([ MyEntity::class, ]); $this->loadFixtureFiles([ './tests/DataFixtures/ORM/my_entities.yml', ]); $this->recoverIdGenerators();
It looks like you don't event need to have a setId() method in your entity.
I also ran into this issue since I wanted some ids to be the same every run since I want to refer them in my debug apps using the UUID
strategy.
What I have done:
1) Wrote a command that wraps 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);}
Do the $metadata
-stuff for all classes you want to have custom ids (App::class
).
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) I created a template to generate the id
like doctrine would.
id (template): id (unique): '<uuid()>'
3) In my custom entity fixture, now I can do the following:
app_custom (extends id): id: 'whatever-i-want' title: 'My custom entity'
4) And if I don't want to use a custom id, I just don't overwrite the id
field:
app_another (extends id): title: 'Just another app with an id I do not care about'
Proof: