-
Notifications
You must be signed in to change notification settings - Fork 87
FormElementManagerV3Polyfill: initializers BC break #100
Comments
I cannot recreate this issue, and I think it may have to do with how you're creating your initializer. I've written the following bits to test it. First, namespace ZendTest\Form\TestAsset;
use Zend\Form\ElementInterface;
use Zend\Stdlib\InitializableInterface;
class InitializableElement implements ElementInterface, InitializableInterface
{
public $dependency = 0;
public $dependencyAtTimeOfInit;
public function init()
{
$this->dependencyAtTimeOfInit = $this->dependency;
}
/**
* {@inheritDoc}
*/
public function setName($name)
{
}
/**
* {@inheritDoc}
*/
public function getName()
{
}
/**
* {@inheritDoc}
*/
public function setOptions($options)
{
}
/**
* {@inheritDoc}
*/
public function setOption($key, $value)
{
}
/**
* {@inheritDoc}
*/
public function getOptions()
{
}
/**
* {@inheritDoc}
*/
public function getOption($option)
{
}
/**
* {@inheritDoc}
*/
public function setAttribute($key, $value)
{
}
/**
* {@inheritDoc}
*/
public function getAttribute($key)
{
}
/**
* {@inheritDoc}
*/
public function hasAttribute($key)
{
}
/**
* {@inheritDoc}
*/
public function setAttributes($arrayOrTraversable)
{
}
/**
* {@inheritDoc}
*/
public function getAttributes()
{
}
/**
* {@inheritDoc}
*/
public function setValue($value)
{
}
/**
* {@inheritDoc}
*/
public function getValue()
{
}
/**
* {@inheritDoc}
*/
public function setLabel($label)
{
}
/**
* {@inheritDoc}
*/
public function getLabel()
{
}
/**
* {@inheritDoc}
*/
public function setMessages($messages)
{
}
/**
* {@inheritDoc}
*/
public function getMessages()
{
}
} Next, I added a test case to public function testInitInitializerShouldBeCalledAfterAllOtherInitializers()
{
$initializer = function ($one, $two) {
if ($one instanceof ElementInterface) {
// v2
$instance = $one;
$container = $two;
} else {
// v3
$instance = $two;
$container = $one;
}
if (! property_exists($instance, 'dependency')) {
return;
}
$instance->dependency = 1;
};
$config = [
'aliases' => [
'Foo' => TestAsset\InitializableElement::class,
],
'invokables' => [
TestAsset\InitializableElement::class => TestAsset\InitializableElement::class,
],
'initializers' => [
$initializer,
],
];
$manager = new FormElementManager(new ServiceManager(), $config);
$foo = $manager->get('Foo');
$this->assertInstanceOf(TestAsset\InitializableElement::class, $foo);
$this->assertEquals(1, $foo->dependency);
$this->assertEquals(1, $foo->dependencyAtTimeOfInit);
} The idea here is to mimic what you did with your I ran this both using the The two differences I see between my test setup and your examples are:
If you look here: you can see that the v3 polyfill attempts to recreate the stacking order such that (a) the Right now, I cannot reproduce using the code you've provided. If you can provide a reproduce case, I'll look into it further. |
Hi, I'm sorry I wasn't clear enough on original post on how this is not a bug related to zend-form itself, but an integration bug on a full stack mvc + module-manager + form, and because those are not dependancies (dev-)required in this component, originally I couldn't make a test. Btw, here it is the full reproducible bug: https://github.com/Slamdunk/zend-form-issue-100 The main sources of this bug are the fact that in a stack like this, the FormElementManager is configured after instantiation:
|
@weierophinney let me know if the reproducible bug provided is clear enough. This bug is forcing me to change all my projects. |
Bug reproduced in #117, closing |
Reproduce issue zendframework#100 without mvc and modulemanager dependencies
Uses the test from zendframework#117 to find a solution for zendframework#100 by overriding `configure()` to first remove the default initializers from the initializer stack if present, and then push them on in the appropriate positions once configuration is complete.
Let's say you have this code (some FQCN are shortened for readibility):
This will output different if using SM v2 or SM v3:
Because by default v2 adds initializers on top of the stack leaving
callElementInit
for last, instead v3 always add initializers on bottom.Although we all know that initializers should be avoided in favour of factories and constructor dependency injection, as of yet there is no way to forward port from SM v2 to SM v3 a full zf modulemanager+mvc stack, because in v3
FormElementManager
is always configured after construction, and soinit
will always be called before custom initializers.A temporary solution would be to move
initializers
config key away and create a customFormElementManagerFactory
to pass them into the constructor.A (very raw) functioning example:
The text was updated successfully, but these errors were encountered: