Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Can you selectively load fixtures in symfony2

When I run

console doctrine:fixtures:load --fixtures=src/App/PeopleBundle/DataFixtures/ORM

I don't want doctrine to purge every table that has an entity. Instead, I only want to purge tables for the fixtures that are in the explicitly specified directory.

However, it seems that, regardless of the target directory, symfony is finding every entity in every bundle, and purging every table associated with each entity.

How can I direct symfony2 to ignore all tables except for the specific tables for which I have written fixtures?

like image 981
Aaron Avatar asked Aug 09 '12 22:08

Aaron


2 Answers

It's really not that hard to go about this the right way. First and foremost, yes, you use --append, but you'll have a load of extra things added that you don't want. So you need to perform some basic checks in your fixtures to see if you actually need to add them (if they're already in the database, you don't).

The example I'm going to show you is a simple one: I have a locators table containing the columns: id and name.

namespace Application\Model\Fixtures;

use Doctrine\Common\DataFixtures\OrderedFixtureInterface,
    Doctrine\Common\DataFixtures\FixtureInterface,
    Doctrine\Common\Persistence\ObjectManager,
    Application\Model\Entity\Locator;

/**
 * Class LoadLocators
 *
 * Pre-populates the locators table
 *
 * @package Application\Model\Fixtures
 */
class LoadLocators implements FixtureInterface, OrderedFixtureInterface
{
    /**
     * @var array The locators names that will be inserted in the database table
     */
    protected $locators = ['id', 'xpath', 'css'];

    /**
     * {@inheritDoc}
     */
    public function load(ObjectManager $manager)
    {
        foreach ($this->locators as $locatorName)
        {
            $locator = $this->findOrCreateLocator($locatorName, $manager);

            /** Check if the object is managed (so already exists in the database) **/
            if (!$manager->contains($locator))
            {
                $manager->persist($locator);
            }
        }

        $manager->flush();
    }

    /**
     * Helper method to return an already existing Locator from the database, else create and return a new one
     *
     * @param string        $name
     * @param ObjectManager $manager
     *
     * @return Locator
     */
    protected function findOrCreateLocator($name, ObjectManager $manager)
    {
        return $manager->getRepository('Application\Model\Entity\Locator')->findOneBy(['name' => $name]) ?: new Locator($name);
    }

    /**
     * {@inheritDoc}
     */
    public function getOrder()
    {
        return 1;
    }
}

The simple change here is that, if the object already exists in the database, find it and use that one instead. It really is that simple.

The command I now run has --append at the end, but it doesn't append if the data already exists.

like image 148
Jimbo Avatar answered Oct 03 '22 00:10

Jimbo


How do you think is Doctrine supposed to figured out what to purge and what not to? There is no information in a fixture telling which entities it will be loading. If you really need this, you'll have to do it manually.

First, you could use the --append option to avoid purging the database. Second, the first thing you could do in your fixtures is to truncate the related tables.

like image 21
Elnur Abdurrakhimov Avatar answered Oct 02 '22 23:10

Elnur Abdurrakhimov