doctrine / data-fixtures

Doctrine2 ORM Data Fixtures Extensions
http://www.doctrine-project.org
MIT License
2.78k stars 224 forks source link

Fixture as a service does not work #283

Closed vitalyiegorov closed 6 years ago

vitalyiegorov commented 6 years ago

Hello, @alcaeus please correct me if I am wrong, maybe I am missing something:

According to the documentation fixtures can [have dependencies] (https://symfony.com/doc/master/bundles/DoctrineFixturesBundle/index.html#accessing-services-from-the-fixtures) and act as services.

But looking into Loader class we just create instance with anything: https://github.com/doctrine/data-fixtures/blob/master/lib/Doctrine/Common/DataFixtures/Loader.php#L193

All services are configured via services.yml and other DI works as expected.

And I get following error:

Type error: Too few arguments to function ...Fixture::__construct(), 0 passed in vendor/doctrine/data-fixtures/lib/Doctrine/Common/DataFixtures/Loader.php on line 210 and exactly 2 expected (Behat\Testwork\Call\Exception\FatalThrowableError)

The only way to figure out this is to use ContainerAwareInterface

vitalyiegorov commented 6 years ago

Was using old version of the bundle

raziel057 commented 6 years ago

@vitalyiegorov Hi, I have the same issue but can't figure what is wrong.

I use symfony 4.1 and here are my version of doctrine/*:

doctrine/annotations              v1.6.0            Docblock Annotations Parser
doctrine/cache                    v1.7.1            Caching library offering an object-oriented API for many cache backends
doctrine/collections              v1.5.0            Collections Abstraction library
doctrine/common                   v2.9.0            Common Library for Doctrine projects
doctrine/data-fixtures            v1.3.1            Data Fixtures for all Doctrine Object Managers
doctrine/dbal                     v2.8.0            Database Abstraction Layer
doctrine/doctrine-bundle          1.9.1             Symfony DoctrineBundle
doctrine/doctrine-cache-bundle    1.3.3             Symfony Bundle for Doctrine Cache
doctrine/doctrine-fixtures-bundle 3.0.2             Symfony DoctrineFixturesBundle
doctrine/event-manager            v1.0.0            Doctrine Event Manager component
doctrine/inflector                v1.3.0            Common String Manipulations with regard to casing and singular/plural rules.
doctrine/instantiator             1.1.0             A small, lightweight utility to instantiate objects in PHP without invoking their constructors
doctrine/lexer                    v1.0.1            Base library for a lexer that can be used in Top-Down, Recursive Descent Parsers.
doctrine/orm                      2.7.x-dev aeef8fa Object-Relational-Mapper for PHP

Do you see something wrong?
weaverryan commented 6 years ago

@raziel057 do you get the exact same error, thrown from the same line of code? Or only something similar? If it's different at all, post the full error please :)

raziel057 commented 6 years ago

@weaverryan In fact I had the exact same error when loading fixtures for my behat tests.

But I was using the following method:

/**
    * @Given I load fixtures from folder :folder
    */
    public function loadFixtures($folder)
    {
        $kernel = $this->getKernel();
        $path = $kernel->getRootDir().$folder;

        $loader = new Loader();
        $loader->loadFromDirectory($path);

        $purger = new ORMPurger();
        $executor = new ORMExecutor($this->manager, $purger);
        $executor->execute($loader->getFixtures(), true);
    }

I fixed the problem by using a ContainerAwareLoader and passing a "@test.service_container" as container:

/**
    * @Given I load fixtures from folder :folder
    */
    public function loadFixtures($folder)
    {
        $kernel = $this->getKernel();
        $path = $kernel->getRootDir().'/'.$folder;

        $loader = new ContainerAwareLoader($this->container);
        $loader->loadFromDirectory($path);

        $purger = new ORMPurger();
        $executor = new ORMExecutor($this->manager, $purger);
        $executor->execute($loader->getFixtures(), true);
    }

My Datafixture:

class LoadCitizenData extends Fixture implements DependentFixtureInterface, ContainerAwareInterface
{
    /**
     * @var ContainerInterface
     */
    private $container;

    public function setContainer(ContainerInterface $container = null)
    {
        $this->container = $container;
    }
   ...
bentcoder commented 6 years ago

Why don't you guys just use $this->container->get(WhateverTheClassIs::class); as described here?

alcaeus commented 6 years ago

For one, the docs don't show $this->container->get but rather inject the dependencies as constructor argument. This is also one of the reasons why you want to declare fixtures as services: that way you don't have to inject the container and have the fixture class fetch whatever dependency is needed but rather wire all dependencies like you would with all other services in your container config (or rely on autowiring).

bentcoder commented 6 years ago

For one, the docs don't show $this->container->get ....

I can see!

screen shot 2018-08-16 at 12 30 22
alcaeus commented 6 years ago

Welp, need to get my eyes checked. The joy of getting older.

BonBonSlick commented 5 years ago

Same https://github.com/doctrine/data-fixtures/issues/295