Thanks to visit codestin.com
Credit goes to github.com

Skip to content

[Doctrine] problem with events #8425

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Closed
sirian opened this issue Jul 5, 2013 · 26 comments
Closed

[Doctrine] problem with events #8425

sirian opened this issue Jul 5, 2013 · 26 comments

Comments

@sirian
Copy link
Contributor

sirian commented Jul 5, 2013

SF 2.3.1
events doesn't work, because appDevDebugProjectContainer has extra lines after return tag:

    protected function getDoctrine_Dbal_DefaultConnectionService()
    {
        $a = new \Doctrine\DBAL\Logging\LoggerChain();
        $a->addLogger(new \Symfony\Bridge\Doctrine\Logger\DbalLogger($this->get('monolog.logger.doctrine', ContainerInterface::NULL_ON_INVALID_REFERENCE), $this->get('debug.stopwatch', ContainerInterface::NULL_ON_INVALID_REFERENCE)));
        $a->addLogger($this->get('doctrine.dbal.logger.profiling.default'));

        $b = new \Doctrine\DBAL\Configuration();
        $b->setSQLLogger($a);

        $c = new \Symfony\Bridge\Doctrine\ContainerAwareEventManager($this);

        return $this->services['doctrine.dbal.default_connection'] = $this->get('doctrine.dbal.connection_factory')->createConnection(array('dbname' => 'test', 'host' => '127.0.0.1', 'port' => NULL, 'user' => 'test', 'password' => 'test', 'charset' => 'UTF8', 'driver' => 'pdo_mysql', 'driverOptions' => array()), $b, $c, array());
        $c->addEventSubscriber(new \FOS\UserBundle\Entity\UserListener($this));
        $c->addEventListener(array(0 => 'prePersist'), $this->get('test_listener'));
    }
@sirian
Copy link
Contributor Author

sirian commented Jul 5, 2013

Problem happens if listener has depends on @doctrine.orm.entity_manager (even in case of deep dependency)

    test_listener:
        class: TestListener
        arguments: [@doctrine.orm.entity_manager]
        tags:
            - { name: doctrine.event_listener, event: prePersist }

@bendavies
Copy link
Contributor

if anyone else was struggling to spot the 'bug', addEventSubscriber and addEventListener are after the return

@peterrehm
Copy link
Contributor

@sirian Why do you even want to inject the entity manager?

As you can see here, you can get the entity manager from LifecycleEventArgs. http://symfony.com/doc/current/cookbook/doctrine/event_listeners_subscribers.html#creating-the-listener-class

If I am trying to reproduce I am getting a circular reference error.

@sirian
Copy link
Contributor Author

sirian commented Jul 9, 2013

@peterrehm it is simplified example. more complex:

    foo: 
        class: Foo
        arguments: [@doctrine.orm.entity_manager]

    test_listener:
        class: TestListener
        arguments: [@foo]
        tags:
            - { name: doctrine.event_listener, event: prePersist }

@stof
Copy link
Member

stof commented Jul 9, 2013

@sirian This is a circular reference. This object graph requires to instantiate the entity manager before instantiating Foo, and to instantiate Foo before the TestListener. But the TestListener needs to be instantiating when building the doctrine EventManager required by the EntityManager. And here, you see the issue: where can we start instantiating ? nowhere.

@peterrehm
Copy link
Contributor

@stof But in any case no code should be generated after a return statement, or what do you think?

@stof
Copy link
Member

stof commented Jul 9, 2013

yes, there is indeed a bug in the code generation.

@peterrehm
Copy link
Contributor

@stof Should a separate issue be opened? What would be the expected result? If it is that circular reference, it should throw an exception?

@peterrehm
Copy link
Contributor

@sirian I was solving that issue once with injecting the event dispatcher to the listener and do such specific action based on an event like user.create. That might solve your issue with some refactoring.

@stof
Copy link
Member

stof commented Jul 9, 2013

@peterrehm yes, circular references should throw an exception

@sirian
Copy link
Contributor Author

sirian commented Jul 10, 2013

@stof as i remember same problem happened even with calls:

    foo: 
        class: Foo
        calls:
            - [setEntityManager, [@doctrine.orm.entity_manager]]

    test_listener:
        class: TestListener
        arguments: [@foo]
        tags:
            - { name: doctrine.event_listener, event: prePersist }

@peterrehm
Copy link
Contributor

@sirian I think the only way is to actually refactor. Which type of injection should in this case not matter.

@sirian
Copy link
Contributor Author

sirian commented Jul 10, 2013

@peterrehm yes, i refactored code in the same day.
But it was difficult to find reson why event listeners didn't work.
So pls add throwing circular reference exception)

@stof
Copy link
Member

stof commented Jul 10, 2013

@sirian injecting through a setter is still a circular reference (the only case where setter injection can workaround a circular reference is when the inlining of private services brings everything back into the same service instantiation)

@dragonwize
Copy link

I ran into this yesterday as well and it took forever to figure out why statements were being written after the return statement.

@fabpot
Copy link
Member

fabpot commented Sep 12, 2013

Which version of Symfony are you using? #7699 might have solved the issue, but it was merged a while ago.

@dragonwize
Copy link

@fabpot 2.3.4 for me

@fabpot
Copy link
Member

fabpot commented Sep 12, 2013

@dragonwize Can you fork the Symfony StandardEdition and modify the configuration in a way to reproduce the error? That would help me spot the bug and fix it. Thanks.

@peterrehm
Copy link
Contributor

@fabpot I have just done this. @dragonwize you don't need to work on this.

If you just clear the cache you will have this in the dumped file:

protected function getDoctrine_Dbal_DefaultConnectionService()
{
    $a = new \Doctrine\DBAL\Logging\LoggerChain();
    $a->addLogger(new \Symfony\Bridge\Doctrine\Logger\DbalLogger($this->get('monolog.logger.doctrine', ContainerInterface::NULL_ON_INVALID_REFERENCE), $this->get('debug.stopwatch', ContainerInterface::NULL_ON_INVALID_REFERENCE)));
    $a->addLogger($this->get('doctrine.dbal.logger.profiling.default'));

    $b = new \Doctrine\DBAL\Configuration();
    $b->setSQLLogger($a);

    $c = new \Symfony\Bridge\Doctrine\ContainerAwareEventManager($this);

    return $this->services['doctrine.dbal.default_connection'] = $this->get('doctrine.dbal.connection_factory')->createConnection(array('dbname' => 'sf2_test', 'host' => '127.0.0.1', 'port' => NULL, 'user' => 'root', 'password' => NULL, 'charset' => 'UTF8', 'driver' => 'pdo_mysql', 'driverOptions' => array()), $b, $c, array());
    $c->addEventListener(array(0 => 'prePersist'), $this->get('acme.demo.doctrinelistener'));

}

I hope this helps you.

@dragonwize
Copy link

@peterrehm thx

@dragonwize
Copy link

@fabpot As mentioned above as well, while the example @peterrehm has given shows the issue in a simple way, it happens even when the entitymanager is passed into dependent argument of the service. In my case it was 3 services deep and so it was not immediately obvious that it was a circular dependency.

@peterrehm
Copy link
Contributor

@dragonwize What do you mean with 3 services deep? Still an EventListener? I guess if the simple example is going to be fixed, yours should be fine as well...

@dragonwize
Copy link

@peterrehm Yes the fix should most likely fix both at the same time. In my case I had a custom service that used the entity manager and another service that required that service and it was what was being passed into my doctrine event subscriber.

@dragonwize
Copy link

Once you see it, it is obviously a circular issue but in can be very difficult to figure that part out so if there is a way to throw an exception on it, I think that is fine.

@fabpot
Copy link
Member

fabpot commented Sep 12, 2013

Can you test the fix in #8999?

@peterrehm
Copy link
Contributor

@fabpot In my sample the exception is now detected:

[Symfony\Component\DependencyInjection\Exception\ServiceCircularReferenceException]
Circular reference detected for service "doctrine.dbal.default_connection", path: "doctrine.dbal.default_connection".

fabpot added a commit to fabpot/symfony that referenced this issue Sep 12, 2013
…umper (closes symfony#8425)

This circular reference cannot be detected by the compiler pass as we
don't check for method arguments there.

The Container itself already detects such circular references at runtime.

So this fix is about circular references that are not detected at
compile time, and are not even detected at runtime because the code that
would cause the detection is never run (generated after a return
statement.)
fabpot added a commit that referenced this issue Sep 12, 2013
This PR was merged into the 2.2 branch.

Discussion
----------

[DependencyInjection] fixed a non-detected circular reference in PhpDumper (closes #8425)

| Q             | A
| ------------- | ---
| Bug fix?      | yes
| New feature?  | no
| BC breaks?    | no
| Deprecations? | no
| Tests pass?   | yes
| Fixed tickets | #8425
| License       | MIT
| Doc PR        | n/a

Commits
-------

ce7de37 [DependencyInjection] fixed a non-detected circular reference in PhpDumper (closes #8425)
@fabpot fabpot closed this as completed Sep 12, 2013
fabpot added a commit that referenced this issue Sep 12, 2013
* 2.2:
  [HttpKernel] added a check for private event listeners/subscribers
  [FrameworkBundle] fixed registration of the register listener pass
  [Form] Fixed regression causing invalid "WHERE id IN ()" statements
  [DependencyInjection] fixed a non-detected circular reference in PhpDumper (closes #8425)
  [Form] Fixed regression in BooleanToStringTransformer from ed83752
  [FrameworkBundle] removed obsolete code
  [Process] Close unix pipes before calling `proc_close` to avoid a deadlock

Conflicts:
	src/Symfony/Bundle/FrameworkBundle/FrameworkBundle.php
	src/Symfony/Component/HttpKernel/DependencyInjection/RegisterListenersPass.php
	src/Symfony/Component/Process/Process.php
fabpot added a commit that referenced this issue Sep 12, 2013
* 2.3:
  [HttpKernel] added a check for private event listeners/subscribers
  [FrameworkBundle] fixed registration of the register listener pass
  [Form] Fixed regression causing invalid "WHERE id IN ()" statements
  [DependencyInjection] fixed a non-detected circular reference in PhpDumper (closes #8425)
  [Form] Fixed regression in BooleanToStringTransformer from ed83752
  [FrameworkBundle] removed obsolete code
  [Process] Close unix pipes before calling `proc_close` to avoid a deadlock
  [Process] Fix process merge in 2.3
  [Intl] made RegionBundle and LanguageBundle merge fallback data when using a country-specific locale
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

No branches or pull requests

6 participants