zendframework / zend-expressive

PSR-15 middleware in minutes!
BSD 3-Clause "New" or "Revised" License
711 stars 197 forks source link

Problem with ApplicationConfigInjectionDelegator and Auryn #611

Closed Musiksammler closed 6 years ago

Musiksammler commented 6 years ago

Hello!

I'm trying to upgrade my expressive-2 application to expressive-3. In my expressive-2 application i'm using this to get all routes from the ConfigProvider Classes:

$app->injectRoutesFromConfig((new \NamespaceA\NamespaceB\ConfigProvider())());

Since this is not possible anymore I try to get it done like explained here: https://docs.zendframework.com/zend-expressive/v3/cookbook/autowiring-routes-and-pipelines/

Like in the documentation in my main ConfigProvider class I've added this:

'delegators' => [
    \Zend\Expressive\Application::class => [
        \Zend\Expressive\Container\ApplicationConfigInjectionDelegator::class,
    ],
],

But now comes the part not working. I am now using Auryn instead of Zend Servicemanager. When installing expressive-3 Auryn gets the config as an ArrayObject and not a plain array. And that's the problem. When I now try to start my application this error pops up:

Fatal error: Uncaught TypeError: Argument 2 passed to Zend\Expressive\Container\ApplicationConfigInjectionDelegator::injectPipelineFromConfig() must be of the type array, object given

So Auryn is giving the config correctly to the delegator class but that one expects another type.

michalbundyra commented 6 years ago

@Musiksammler IMHO it's a bug, it should work also when config is not an array but ArrayObject (as it is for some containers). Please see my fix #612

weierophinney commented 6 years ago

Another approach you can use can be accomplished within your config/routes.php or config/pipeline.php files, and would look like this:

use Psr\Container\ContainerInterface;
use Zend\Expressive\Application;
use Zend\Expressive\Container\ApplicationConfigInjectionDelegator;
use Zend\Expressive\MiddlewareFactory;

return function (Application $app, MiddlewareFactory $factory, ContainerInterface $container) : void {
    $config = $container->get('config');
    ApplicationConfigInjectionDelegator::injectRoutesFromConfig($app, $config->getArrayCopy());
};

The above allows you to cast the configuration to an array before attempting to use it for route injection.

In terms of a long-term solution, we cannot do so currently without a BC break.

Most containers allow returning arbitrary values from get(). However, a few, such as Auryn and Aura.Di, only allow return objects, and the wrappers we have for them thus return an ArrayObject instance for the config. This means we either need to allow ArrayObject as well as array anywhere we accept configuration, or we need to always return one or the other.