Welcome to Abdul Malik Ikhsan's Blog

Start Using Middleware Approach with new zend-mvc

Posted in Tutorial PHP, Zend Framework, Zend Framework 2 by samsonasik on March 1, 2016

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