Search code examples
phpsymfonydoctrinefixtures

Loading dozens of data fixtures in a neat manner


I have a Media entity in an app I'm working on that has associations with several other entities: Speaker, Tag, Category, etc.

In the code below I've shown a fixture I've written to create some test-data. It's obviously very long in order to setup and assign the numerous relations between the data.

public function load(ObjectManager $manager)
{
    $videoType = new Mediatype();
    $videoType->setName('video');
    $videoType->setType('video');

    $manager->persist($videoType);

    $speaker1 = new Speaker();
    $speaker1->setName('Joe Bloggs');

    $speaker1->setBiography('Joe Bloggs bio.');

    $manager->persist($speaker1);

    $category1 = new Category();
    $category1->setName('PHP');
    $category1->setSlug('php');

    $manager->persist($category1);

    $tag1 = new Tag();
    $tag1->setName('PHPNW');
    $tag1->setSlug('phpnw');

    $manager->persist($tag1);

    $video1 = new Media();
    $video1->setMediatype($videoType);
    $video1->setSpeakers(
        new ArrayCollection(
            array(
                $speaker1
            )
        )
    );

    $video1->setCategories(
        new ArrayCollection(
            array(
                $category1
            )
        )
    );

    $video1->setTags(
        new ArrayCollection(
            array(
                $tag1
            )
        )
    );

    $video1->setDate(new \Datetime());
    $video1->setCreationDate(new \DateTime());
    $video1->setTitle('My video about PHP');
    $video1->setDescription('A video about PHP!');
    $video1->setContent('http://some.video-url.com');
    $video1->setLength('20:00:00');
    $video1->setRating(2.5);
    $video1->setVisits(100);
    $video1->setLanguage('EN');
    $video1->setHostName('PHP');
    $video1->setHostUrl('php');
    $video1->setStatus('pub');
    $manager->persist($video1);
    $manager->flush();
}

Now I want to replace this fixture with real data and load a dozen or so Media entities in one fixture. I could copy and paste it a dozen times and make change the data but that's messy and harder to maintain. Is there an nice way to load numerous entities of the same type like this?


Solution

  • I realised that the doctrine/data-fixtures bundle already does exactly what I wanted.

    To do this I load each entity in their own fixture and do $this->addReference('admin-user', $user); to access it from another fixture using $this->getReference('admin-user');

    Loading fixtures that are dependencies is easy too:

    public function getDependencies()
    {
        // fixture classes that this fixture is dependent on
        return array('MyDataFixtures\MyOtherFixture'); 
    }
    

    So now my fixture looks like this:

    public function load(ObjectManager $manager)
    {
        $video1 = new Media();
        $video1->setMediatype($this->getReference('video'));
        $video1->setSpeakers(
            new ArrayCollection(
                array(
                    $this->getReference('joe-bloggs')
                )
            )
        );
    
        $video1->setCategories(
            new ArrayCollection(
                array(
                    $this->getReference('php')
                )
            )
        );
    
        $video1->setTags(
            new ArrayCollection(
                array(
                    $this->getReference('phpnw')
                )
            )
        );
    
        $video1->setDate(new \Datetime());
        $video1->setCreationDate(new \DateTime());
        $video1->setTitle('My video about PHP');
        $video1->setDescription('A video about PHP!');
        $video1->setContent('http://some.video-url.com');
        $video1->setLength('20:00:00');
        $video1->setRating(2.5);
        $video1->setVisits(100);
        $video1->setLanguage('EN');
        $video1->setHostName('PHP');
        $video1->setHostUrl('php');
        $video1->setStatus('pub');
    
        $manager->persist($video1);
        $manager->flush();
    }
    
    /**
     * Load this fixtures dependencies
     * @see https://github.com/doctrine/data-fixtures
     *
     * @return array
     */
    public function getDependencies()
    {
        return array(
            '...\LoadMediatypeData',
            '...\LoadSpeakerData',
            '...\LoadCategoryData',
            '...\LoadTagData'
        );
    }