Creates middleware layer on Zend Framework 2. Useful when it's necessary to make some work between route and controller dispatch phases.
Add this project in your composer.json
:
"require": {
"muriloamaral/middleware": "dev-master"
}
Now tell composer to download Middleware by running the command:
$ php composer.phar update
Enabling it in your config/application.config.php
file.
return array(
'modules' => array(
// ...
'Middleware',
),
// ...
);
On your config file set your global and local middlewares. For instance:
module/Application/config/module.config.php
// ...
'middlewares' => array(
'global' => array(
'my.first.middleware',
'my.second.middleware'
),
'local' => array(
'Application\Controller\IndexController' => array(
'my.third.middleware'
),
),
),
// ...
'service_manager' => array(
// ...
'invokables' => array(
// ...
'my.first.middleware' => 'Application\Middleware\First',
'my.second.middleware' => 'Application\Middleware\Second',
// ...
),
// ...
'services' => array(
// ...
'my.third.middleware' => function($request, $response, $next) {
// My code here. For instance:
var_dump($request->getHeader('user-agent'));
$next();
},
// ...
),
// ...
),
// ...
Define your middleware classes:
module/Application/src/Application/Middleware/First.php
namespace Application\Middleware;
class First
{
public function __invoke($request, $response, $next)
{
// My code here. For instance:
var_dump($request->getHeader('user-agent'));
$next(); // call the next middleware
// Run code after all middlewares run
}
}
module/Application/src/Application/Middleware/Second.php
namespace Application\Middleware;
class Second
{
public function __invoke($request, $response, $next)
{
// My code here. For instance:
var_dump($request->getHeader('user-agent'));
$next(); // call the next middleware
// Run code after all middlewares run
}
}
Middlewares on global scope will be executed everytime a request is made.
Middlewares on local scope will be executed only if the current controller declares a middleware.
P.S: local middlewares are executed after global middlewares.
In this case, my.first.middleware
and my.second.middleware
will be always executed no matter what route is being called. Whereas my.third.middleware
will be executed only when
Application\Controller\IndexController is being called. Thus, if we access Application\Controller\IndexController first, second and third middlewares will be executed.
It's also possible to access ServiceManager within your middleware classes. It's only necessary to implement ServiceLocatorAwareInterface. For instance:
module/Application/src/Application/Middleware/First.php
namespace Application\Middleware;
use Zend\ServiceManager\ServiceLocatorAwareInterface;
use Zend\ServiceManager\ServiceLocatorInterface;
class First implements ServiceLocatorAwareInterface
{
protected $serviceLocator;
public function __invoke($request, $next, $redirect)
{
// My code here. For instance:
$config = $this->serviceLocator->get('config');
}
public function setServiceLocator(ServiceLocatorInterface $serviceLocator)
{
$this->serviceLocator = $serviceLocator;
}
public function getServiceLocator()
{
return $this->serviceLocator;
}
}
If you don't want to declare middlewares inside your service manager config key, you can use the abstract service factory provided by us.
-
Define your middleware class, you need to implement
Middleware\MiddlewareInterface
.module/Application/src/Application/Middleware/First.php
namespace Application\Middleware; use Closure; use Zend\Http\PhpEnvironment\Request; use Zend\Http\PhpEnvironment\Response; use Middleware\MiddlewareInterface; class First implements MiddlewareInterface { public function __invoke(Request $request, Response $response, Closure $next) { // My code here. } }
-
Configure your middleware
module/Application/config/module.config.php
// ... 'middlewares' => array( 'global' => array( 'Application\Middleware\First' ) ), // ...
-
Configure the abstract service factory
module/Application/config/module.config.php
// ... 'service_manager' => array( // ... 'abstract_factories' => array( // ... 'Middleware\Factory\MiddlewareAbstractServiceFactory' ), // ... ), // ...
You can provide any callable as a middleware name. Such as functions, static methods and so on. For instance:
'middlewares' => array(
'global' => array(
'my.first.middleware',
'my.second.middleware',
'MyNamespace\MyClass::MyStaticMethod', // Static method sample
function ($request, $response, $next) // Function sample
{
var_dump($request->getHeader('user-agent'));
$next();
}
),
'local' => array(
'Application\Controller\IndexController' => array(
'my.third.middleware'
),
),
),