Skip to content
This repository has been archived by the owner on Jan 30, 2020. It is now read-only.

Declaring a Collection with array notation: target element doesn't get it's dependencies #58

Closed
silentvick opened this issue Apr 18, 2016 · 3 comments

Comments

@silentvick
Copy link

silentvick commented Apr 18, 2016

I get this error with a form that has a Collection-element targeting a Fieldset:

Catchable fatal error: Argument 1 passed to DoctrineModule\Stdlib\Hydrator\DoctrineObject::__construct()
must implement interface Doctrine\Common\Persistence\ObjectManager, null given,
called in /var/www/foo.dev/module/Post/src/Post/Form/FooFieldset.php on line 25
and defined in /var/www/foo.dev/vendor/doctrine/doctrine-module/src/DoctrineModule/Stdlib/Hydrator/DoctrineObject.php on line 68

Here is Form example:

<?php
// ...

class FooForm extends Form
{
    public function init()
    {
        $this->add(array(
            'name'    => 'foo',
            'type'    => 'Zend\Form\Element\Collection',
            'options' => array(
                'count' => 1,
                'target_element' => array(
                    'type' => 'Post\Form\BarFieldset',
                ),
            ),
        ));
    }
}

And the Fieldset:

<?php
// ...
use DoctrineModule\Stdlib\Hydrator\DoctrineObject as DoctrineHydrator;

class BarFieldset extends Fieldset implements ObjectManagerAwareInterface
{
    public function init()
    {
        // here $objectManager is null
        $this->setHydrator(new DoctrineHydrator($this->getObjectManager()));

        $this->add(array(
            'name' => 'bar',
            'type' => 'Text',
        ));
    }

    public function getObjectManager()
    {
        return $this->objectManager;
    }

    public function setObjectManager(ObjectManager $objectManager)
    {
        $this->objectManager = $objectManager;
    }
}

I have ObjectManagerAwareInitializer that passes ObjectManager to any class that implements ObjectManagerAwareInterface. It looks like Fieldset doesn't get it's dependencies at a proper time (when init() is called).

But it works if I get Fieldset manually (almost) like this:

// inside Form's init()
$element = new \Zend\Form\Element\Collection();
$element->setName('foo');
$element->setTargetElement(
    $this->getFormFactory()->getFormElementManager()->get('Form\FooFieldset')
);

$this->add($element);

It wasn't an issue in ZF 2.4. (Right now I'm at 2.5.1)

@bfolliot
Copy link

I have the same issue with zend-form 2.8.0, zend-servicemanager 2.7.5 and zend-mvc 2.7.7

@weierophinney
Copy link
Member

First off, I'm having trouble replicating this for a few reasons:

  • Your error references FooFieldset, but you only provide your BarFieldset definition; as such, I don't know for certain what is being executed.
  • I have no idea how you're configuring your form, filters, or validators. You indicate the issue only happens when using the FormElementManager indirectly (via factories?), but not during manual instantiation. As such, I need the minimum amount of configuration that will reproduce the issue.
  • My suspicion is that this is an integration issue with the DoctrineModule, as it looks like you're expecting an initializer or similar to inject the Doctrine ObjectManager, and it's not. If this is the case, this issue and Using Initializers with Composed Object Collections #64 are likely duplicates; the question is whether this is due to changes in zend-form, or DoctrineModule providing configuration that is not forwards-compatible.

I'll work on #64, as it appears to provide enough information for me to be able to reproduce the problem. If you can come up with the minimum code required to reproduce your issue, preferably without requiring the DoctrineModule, please create a gist with it or submit a pull request containing a unit test for it.

@weierophinney
Copy link
Member

Actually, I think I know what the issue is.

Prior to 2.7, the default initializers (injectFactory() and callElementInit()) were injected after any initializers passed during configuration. They are now configured prior. I'll submit a patch shortly to correct that.

weierophinney added a commit to weierophinney/zend-form that referenced this issue Apr 28, 2016
Per zendframework#58 and zendframework#64, 2.7.0 introduced a regression due to the fact that the
default initializers, `injectFactory()` and `callElementInit()`, were
registered *prior* to delegating to the parent constructor instead of
*afterwards*. This led to problems when the order of initializers was
important (e.g., if an initializer was practicing setter injection, and
the injected instance was expected when `init()` was called by
`callElementInit()`).

This patch provides a test that asserts the expected behavior, and
updates the `FormElementManager` constructor to properly inject the
initializers after calling the parent constructor.
Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
Labels
None yet
Projects
None yet
Development

No branches or pull requests

3 participants