Config-driven vs. programmatic approach
wesperinteractive opened this issue · 2 comments
Adding routed middleware via config-driven approach:
In my configuration i have one route:
namespace Cms;
return [
[
'name' => 'cms::index',
'path' => '/cms',
'middleware' => Action\IndexAction::class,
'allowed_methods' => ['GET'],
]
];
The programmatic_pipeline directive is set to true, so i use the $app->injectRoutesFromConfig() method to add my route to the application (in public/index.php):
$app = $container->get(\Zend\Expressive\Application::class);
$app->injectRoutesFromConfig();
$app->run();
Adding routed middleware via programmatic approach:
Doing the same via programmatic approach (in public/index.php):
$app = $container->get(\Zend\Expressive\Application::class);
$app->get('/cms', 'Cms\Action\IndexAction', 'cms::index');
$app->run();
The problem:
In config-driven approach the routed middleware is not prepared in the route method of the Application object.
https://github.com/zendframework/zend-expressive/blob/master/src/Application.php#L294
The $path is an instance of Router/Route, the $route variable will be defined (line 304), the routed middleware won't be prepared (line 312) and won't be stored in the route.
The routed middleware will be prepared only later in the DispatchMiddleware (https://github.com/zendframework/zend-expressive/blob/master/src/Middleware/DispatchMiddleware.php#L72). The prepared routed middleware won't be stored here either.
In programmatic approach the routed middleware is always prepared and stored in the route (in the route method of the Application).
The result of the different behavior:
Calling the getMatchedMiddleware method on the RouteResult object will return a string (Cms\Action\IndexAction) or an object (LazyLoadingMiddleware) depending on what approach was used.
Dependency used in the example:
namespace Cms;
use Zend\ServiceManager\Factory\InvokableFactory;
return [
'factories' => [
Action\IndexAction::class => InvokableFactory::class
]
];
Some more details:
config-driven calls $app->route(Route);
with a Route object.
https://github.com/zendframework/zend-expressive/blob/master/src/ApplicationConfigInjectionTrait.php#L167
programmatic calls $app->route(...$routeArgs);
with some strings and arrays.
https://github.com/zendframework/zend-expressive/blob/master/src/Application.php#L160
That's why it's skipped for config-driven approach:
https://github.com/zendframework/zend-expressive/blob/master/src/Application.php#L303
This is fixed in versions 2.2+ and 3.0+.