Middleware overview

What is Middleware in Polavi?

In Polavi application, Middleware is a Class extends Polavi\Middleware\MiddlewareAbstract abstract class

This class is a simple class with 1 required method: “__invoke()”.

This method takes 2 mandatory arguments: Request $request and Response $response and 1 optional argument is $delegate

class AddCatalogMenuMiddleware extends MiddlewareAbstract
{
public function __invoke(Request $request, Response $response, $delegate = null)
{
if(!$request->isAdmin())
return $delegate;
$this->getContainer()->get(NavigationManager::class)
->addItem(
'catalog',
'Catalog',
'',
'database'
)
->addItem(
'products',
'All product',
$this->getContainer()->get(Router::class)->generateUrl('product.grid'),
'list',
'catalog'
)
->addItem(
'categories',
'All category',
$this->getContainer()->get(Router::class)->generateUrl('category.grid'),
'list',
'catalog'
);
return $delegate;
}
}

Typically there are 2 types of middleware in Polavi application.

Core middleware

  • Will be executed in all request
  • Located in `app/Polavi/src/Middleware`
  • Can be registered using event listener

Routed middleware

  • Will be executed in specified route
  • Located inside a module/Middleware folder
  • Registered by using `routes.php` file in each module

What does a middleware do?

A single middleware will receive $request and $response. It also can access to Container object by using “getContainer” method and from here is can call services.

We try to apply Single responsibility principle to middleware. Do not make a middleware over complicated. If you have several things to be done then create several middleware and each of them can take a part of the job.

Whatever returned from previous middleware will be passed to the next middleware as a third argument ($delegate). The idea is if you have nothing to send to the next middleware, send what you received. In our case, “return $delegate;” if you don’t have anything for next middleware.

How to register middleware for a new route?

In routes.php file of your module, when you define a route you can register a list of default middleware by providing a list of middleware class name as a third argument

$router->addAdminRoute('category.save', 'POST', '/category/save[/{id:\d+}]', [
\Polavi\Module\Catalog\Middleware\Category\Save\ValidateMiddleware::class,
\Polavi\Module\Catalog\Middleware\Category\Save\UpdateMiddleware::class,
\Polavi\Module\Catalog\Middleware\Category\Save\CreateMiddleware::class
]);

How to register a existed routed middleware?

To register a middleware to a specified exited route you can use “register.{route identify}.middleware” event.

For example in events.php file of your module

$eventDispatcher->addListener(
"register.widget.grid.middleware",
function (\Polavi\Services\MiddlewareManager $middlewareManager) {
$middlewareManager->registerMiddleware(\Polavi\Module\Catalog\Middleware\Widget\FeaturedProduct\EditMiddleware::class, 1);
$middlewareManager->registerMiddleware(\Polavi\Module\Catalog\Middleware\Widget\ProductFilter\EditMiddleware::class, 1);
}
);

In above example “widget.grid” is a route identify. Your middleware will be called when you go to Widget list from backend.

How to register a core middleware?

Sometime, you might want to have a middleware which will be executed in all request. You can register it as a core middleware by using an event listener

In events.php file of your module

$eventDispatcher->addListener(
'register.core.middleware',
function (\Polavi\Services\MiddlewareManager $middlewareManager) {
$middlewareManager->registerMiddleware(\Polavi\Module\Catalog\Middleware\Core\AddCatalogMenuMiddleware::class, 81);
},
0
);

You can register your middleware using “registerMiddleware” and provide position as second argument. If you want your middleware to be executed after or before specified middleware you can use “registerMiddlewareBefore” or “registerMiddlewareAfter”