Start Using Middleware Approach with new zend-mvc
zend-mvc 2.7.0 is coming, beside of the forward compatibility with V3 components, there is new middleware listener that allow us to do Dispatching PSR-7 middleware. The middleware can be an invokable class with __invoke()
method like the following:
function __invoke($request, $response) { $response->getBody()->write('Hello World!'); return $response; }
Ok, let’s start try it, create new project:
$ composer create-project zendframework/skeleton-application:dev-master newzf
After composer create-project
done, as usual, you will get new project. zend-mvc 2.7.0 released today, so, You should get zend-mvc 2.7.0 already by run:
$ composer update
Now, We can create a middleware, for example, a HomeAction
middleware:
namespace Application\Middleware; class HomeAction { public function __invoke($request, $response) { $response->getBody()->write('Hello World!'); return $response; } } // module/Application/src/Application/Middleware/HomeAction.php
We then can replace the ‘home’ route:
namespace Application; // ... 'home' => [ 'type' => 'Literal', 'options' => [ 'route' => '/', 'defaults' => [ 'middleware' => Middleware\HomeAction::class, ], ], ], // ... // module/Application/config/module.config.php
As the Application\Middleware\HomeAction
is a service, then it need to be registered in service_manager
:
namespace Application; use Zend\ServiceManager\Factory\InvokableFactory; // ... 'service_manager' => [ 'factories' => [ Middleware\HomeAction::class => InvokableFactory::class, ], ] // ... // module/Application/config/module.config.php
Everything seems configured correctly, now, let’s start the server:
$ php -S localhost:8080 -t public
And open up in the browser: http://localhost:8080 ! So, the “Hello World!” will be shown!
Work with ViewModel
So, you now want to work with ViewModel with its layout, You can! Let’s do it. You can inject the Middleware with the Renderer and ViewManager.
use Zend\View\Renderer\PhpRenderer; use Zend\Mvc\View\Http\ViewManager; class HomeAction { // ... public function __construct( PhpRenderer $renderer, ViewManager $view ) { $this->renderer = $renderer; $this->view = $view; } // ... } // module/Application/src/Application/Middleware/HomeAction.php
To make it work, we can create factory for it:
namespace Application\Middleware; class HomeActionFactory { public function __invoke($container) { $viewRenderer = $container->get('ViewRenderer'); $viewManager = $container->get('ViewManager'); return new HomeAction($viewRenderer, $viewManager); } } // module/Application/src/Application/Middleware/HomeActionFactory.php
Based on the factory above, we then need to update the registered Application\Middleware\HomeAction
service:
namespace Application; // ... 'service_manager' => [ 'factories' => [ Middleware\HomeAction::class => Middleware\HomeActionFactory::class, ], ] // ... // module/Application/config/module.config.php
So, now, you can update the Middleware as follows:
use Zend\View\Renderer\PhpRenderer; use Zend\Mvc\View\Http\ViewManager; use Zend\View\Model\ViewModel; use Zend\Diactoros\Response\HtmlResponse; class HomeAction { // ... public function __invoke($request, $response) { $viewModel = new ViewModel(); $viewModel->setTemplate('application/index/index'); $layout = $this->view->getViewModel(); $layout->setVariable( 'content', $this->renderer->render($viewModel) ); return new HtmlResponse($this->renderer->render($layout)); } // ... } // module/Application/src/Application/Middleware/HomeAction.php
Done! đ
References:
– https://gist.github.com/weierophinney/b9dbff92e4446f49e248
– https://github.com/weierophinney/2015-10-22-ZF3
[…] Malik Ikhsan posted on how you can use middleware in the upcoming version of ZendMvc, Start Using Middleware Approach with new zend-mvc. Version 2.7.0 of the Mvc component includes forward compatibility features that make this […]
A naive question, if I may: what’s it for? Not that I doubt that this is really cool and great for solving certain situations. I haven’t seen any examples of how this would be useful in real life.
you can read further more about middleware here:
– https://mwop.net/blog/2015-01-08-on-http-middleware-and-psr-7.html
– http://zendframework.github.io/zend-mvc/cookbook/middleware-in-listeners/
– https://zendframework.github.io/zend-expressive/getting-started/features/
– https://github.com/zendframework/zend-stratigility/blob/master/doc/book/middleware.md
Hey, Nice article, really appreciate your concern over explaining complected things. However I’m wondering, can we wrap an ordinary Controller with a middleware. Is it a good design?
I mean, if I handle the authentication on middleware and if valid passing the same request to a Controller action. Is it valid?
Thank you. You can use middleware within event listener https://docs.zendframework.com/zend-mvc/cookbook/middleware-in-listeners/