使用Symfony + Doctrine的环境特定数据夹具

时间:2012-08-05 16:13:33

标签: symfony doctrine-orm

使用Smyfony2和Doctrin2,可以使用以下示例创建数据夹具:http://symfony.com/doc/current/bundles/DoctrineFixturesBundle/index.html

我希望能够使用此概念进行测试,以便setup / teardown可以为功能测试创建纯测试数据环境。如何在功能测试期间运行一组特定的仅测试夹具,如何将这些夹具与我的标准夹具分开,以便控制台命令忽略它们?

似乎这样做的方法是复制doctrine:fixtures控制台命令的功能并将测试装置存储在其他位置。有没有人有更好的解决方案?

2 个答案:

答案 0 :(得分:38)

按目录分解灯具的另一种方法是使用自定义灯具类。然后,您的fixture类将扩展此类并指定实际加载的环境。

<?php

use Doctrine\Common\DataFixtures\FixtureInterface;
use Doctrine\Common\Persistence\ObjectManager;
use Symfony\Component\DependencyInjection\ContainerAwareInterface;
use Symfony\Component\DependencyInjection\ContainerInterface;
use Symfony\Component\HttpKernel\KernelInterface;

/**
 * Provides support for environment specific fixtures.
 *
 * This container aware, abstract data fixture is used to only allow loading in
 * specific environments. The environments the data fixture will be loaded in is
 * determined by the list of environment names returned by `getEnvironments()`.
 *
 * > The fixture will still be shown as having been loaded by the Doctrine
 * > command, `doctrine:fixtures:load`, despite not having been actually
 * > loaded.
 *
 * @author Kevin Herrera <kevin@herrera.io>
 */
abstract class AbstractDataFixture implements ContainerAwareInterface, FixtureInterface
{
    /**
     * The dependency injection container.
     *
     * @var ContainerInterface
     */
    protected $container;

    /**
     * {@inheritDoc}
     */
    public function load(ObjectManager $manager)
    {
        /** @var KernelInterface $kernel */
        $kernel = $this->container->get('kernel');

        if (in_array($kernel->getEnvironment(), $this->getEnvironments())) {
            $this->doLoad($manager);
        }
    }

    /**
     * {@inheritDoc}
     */
    public function setContainer(ContainerInterface $container = null)
    {
        $this->container = $container;
    }

    /**
     * Performs the actual fixtures loading.
     *
     * @see \Doctrine\Common\DataFixtures\FixtureInterface::load()
     *
     * @param ObjectManager $manager The object manager.
     */
    abstract protected function doLoad(ObjectManager $manager);

    /**
     * Returns the environments the fixtures may be loaded in.
     *
     * @return array The name of the environments.
     */
    abstract protected function getEnvironments();
}

你的灯具最终看起来像这样:

<?php

namespace Vendor\Bundle\ExampleBundle\DataFixtures\ORM;

use AbstractDataFixture;
use Doctrine\Common\Persistence\ObjectManager;

/**
 * Loads data only on "prod".
 */
class ExampleData extends AbstractDataFixture
{
    /**
     * @override
     */
    protected function doLoad(ObjectManager $manager)
    {
        // ... snip ...
    }

    /**
     * @override
     */
    protected function getEnvironments()
    {
        return array('prod');
    }
}

我认为这应该适用于ORM和ODM数据夹具。

答案 1 :(得分:17)

最简单的方法是将您的灯具放入不同的文件夹,然后使用php app/console doctrine:fixtures:load --fixtures=../src/Acme/TestBundle/DataFixtures/ORM/test命令加载它们。 fixtures选项必须指向app app文件夹的相对路径!

然后您可以将数据拆分为初始数据,测试数据等,或者根据需要创建开发,测试,登台,生成固定装置。

如果你想混淆它们,我不知道比我做的更好的解决方案:我创建一个所有灯具所在的“模板”文件夹。在我的dev文件夹中,我创建了一个扩展了正确的类从模板中获取fixture类并调整需要调整的内容(如覆盖getOrder方法)。它并不完美,我想可以考虑扩展fixtures:load命令以获取多条路径,但它对我有用。