As Matthew kindly requested in Slack thread here is an example of
ValidatorManager not calling custom validator factory.
Same goes for
FormElementManager not calling form factory.
Simply comment out any (or both) of two defined delegators.
As Matthew kindly requested in Slack thread here is an example of
Just a few initial comments, as I had to dive a bit further into code to understand what’s being wired and where.
config/config.php, add entries for each of the
ConfigProviderclasses of the ZF components installed (e.g.,
Zend\Filter\ConfigProvider::class), instead of adding
config/autoload/<component>.global.phpfiles that import and invoke them. It’s simpler to see which components are registered, plays nicer with zend-component-installer, and follows the conventions of default Expressive applications.
- One problem highlighted is that
App\InputFilter\InputFilter, and the latter is not being injected with the custom validator
App\Validator\Validator, which is provided via
I have update the example to reflect your suggestion and slightly modified
FormFactory so that commenting out
FormElementDelegator will cause an exception to be thrown because
FormFactory is not called
I’ve done the following:
- Cloned your repository
composer install. When I did, it prompted me to inject the ConfigProvider from zend-filter, which I did.
- I then ran
php -S 0:8080 -t public/ public/index.phpto initialize a web server.
- I navigated to
https://localhost:8080/testto test the form.
As expected, this worked fine.
I then did as you suggested, and commented out first the
FormElementManager delegator in
App\ConfigProvider, and then the
ValidatorManager delegator. This continued to work.
And then I remembered to enable development mode, to ensure the configuration cache was cleared:
composer development-enable. Once I did this, I repeated the steps above, refreshing the page at each step. At the step where I commented out the
FormElementManager delegator, I ran into the problem.
whoops reports that the issue is within
App\Form\Form::init(), at the line that tests if
!$this->something, which triggers an exception. This demonstrates that the
App\Form\FormFactory is not being used to instantiate the form instance.
If I instead comment out the
ValidatorManager entry, I do not see an error until after submission, at which point
App\Validator\Validator::isValid() raises an exception because its first argument, assigned to the property
$test, is null — indicating that its factory was not invoked.
So, at this point, I have something reproducible. I’ll see what I can find from here.
Okay, I figured out the issue, and it affects pretty much all of these
In zend-mvc applications, we tie into zend-modulemanager, and have integration in the
Module class of each that informs
Zend\ModuleManager\Listener\ServiceListener of configuration keys associated with each plugin manager. Once bootstrap is over, it merges configuration under that key in order to configure the associated plugin manager.
What this means is that the various keys such as
form_elements, etc. have meaning in zend-mvc applications, but not currently in Expressive applications.
This is clearly a serious issue, and I’m not 100% sure how to manage it. I think we may be able to do it via the factory for each plugin manager, however. They could look for the config service and relevant config key, and, if found use the value to configure the plugin manager before returning it.
To be on the safe side, we’d check to see if the
ServiceListener service is present before doing so, as we would not want to double-inject. (That said, this approach may also mean we no longer need to use that functionality, which could be fantastic.)
I’ll keep this post updated with links to pull requests as I make them.
So glad you could reproduce the problem! Really looking forward to the bugfix. Thanks for the patience for understanding the problem and your time looking into this case - I’m sure Expressive will profit a lot in sense of ZF component usage.
First patch is for zend-validator: https://github.com/zendframework/zend-validator/pull/168
Second patch is for zend-form: https://github.com/zendframework/zend-form/pull/164
Third patch is for zend-filter: https://github.com/zendframework/zend-filter/pull/56
Fourth patch is for zend-inputfilter: https://github.com/zendframework/zend-inputfilter/pull/137
Fifth patch is for zend-hydrator: https://github.com/zendframework/zend-hydrator/pull/59
Sixth patch is for zend-i18n: https://github.com/zendframework/zend-i18n/pull/74
Seventh and final patch is for zend-log: https://github.com/zendframework/zend-log/pull/74
All releases are done!
- zend-log 2.9.2
- zend-i18n 2.7.4
- zend-hydrator 2.2.2
- zend-filter 2.7.2
- zend-validator 2.9.1
- zend-inputfilter 2.7.4
- zend-form 2.10.2
^<version> in your
composer.json files (or run
composer require "zendframework/<component>:^<version>"; alternately, just run
composer update), and you should now have something working!
I’ve just tried that with the sample app you provided, commenting out the two delegator factories you provided, and all is working now!
Works like a charm
Great job guys! Looking forward to test that myself…
Quite curious if this addresses some of the issues you’ve raised in the past, @RalfEggert!
Now I just need to work on the navigation stuff with @froschdesign sometime in the near future so we can get that sorted!
Yes, it does solve my issues. My /config/container.php file looked like this before the update:
use Zend\Filter\FilterPluginManager; use Zend\Form\FormElementManager\FormElementManagerV3Polyfill; use Zend\Hydrator\HydratorPluginManager; use Zend\InputFilter\InputFilterPluginManager; use Zend\ServiceManager\Config; use Zend\ServiceManager\ServiceManager; use Zend\Validator\ValidatorPluginManager; // Load configuration $config = require __DIR__ . '/config.php'; // Build container $container = new ServiceManager(); (new Config($config['dependencies']))->configureServiceManager($container); // Inject config $container->setService('config', $config); /** @var HydratorPluginManager $hydratorManager */ $hydratorManager = $container->get('HydratorManager'); $hydratorManager->configure($config['hydrators']); /** @var FilterPluginManager $filterManager */ $filterManager = $container->get('FilterManager'); $filterManager->configure($config['filters']); /** @var ValidatorPluginManager $validatorManager */ $validatorManager = $container->get('ValidatorManager'); $validatorManager->configure($config['validators']); /** @var InputFilterPluginManager $inputFilterManager */ $inputFilterManager = $container->get('InputFilterManager'); $inputFilterManager->configure($config['input_filters']); /** @var FormElementManagerV3Polyfill $formElementManager */ $formElementManager = $container->get('FormElementManager'); $formElementManager->configure($config['form_elements']); return $container;
Now I can shorten it to this:
use Zend\Filter\FilterPluginManager; use Zend\Form\FormElementManager\FormElementManagerV3Polyfill; use Zend\Hydrator\HydratorPluginManager; use Zend\InputFilter\InputFilterPluginManager; use Zend\ServiceManager\Config; use Zend\ServiceManager\ServiceManager; use Zend\Validator\ValidatorPluginManager; // Load configuration $config = require __DIR__ . '/config.php'; // Build container $container = new ServiceManager(); (new Config($config['dependencies']))->configureServiceManager($container); // Inject config $container->setService('config', $config); return $container;
Without these extra lines all custom form elements, validators, and stuff weren’t found. After upgrading, they are.
little late, but wanted to reply on this again. Updated packages, removed my workaround and it worked like expected for custom filters and validators. Really great!
I think this was a huge step forward for using these packages inside Expressive context and I’m really happy to see the benefits Matthew pointed out in his blog post about this. From a question inside slack to a complex series of releases, that fix the problem. And many people being involved to get the problem solved.
Working now ~10 years with ZF. ZF2 and ModuleManager was a huge step forward, but all the work @matthew did in relation to standards and Expressive - it feels just right. Working now 4 weeks with Expressive2 and there was no situation I didn’t liked it. No magic needed, so flexible to use - v2 just nailed it.