Welcome to Abdul Malik Ikhsan's Blog

Middleware implementation in Penny Framework

Posted in Penny Framework, Tutorial PHP by samsonasik on December 6, 2015

Penny is a microframework that has different idea for accomplishing middleware implementation. If we found other frameworks that implements this signatures:

function ($request, $response, $next = null);

In Penny Framework, Middleware implemented via listener that has priority that we call before or/and after. If we need to initialize application flow, you may use ‘bootstrap’ event:

// config/di.php
use App\Middleware\BootstrapMiddleware;
use function DI\decorate;

return [
    'event_manager' => decorate(function($eventManager, $container) {

        $eventManager->attach(
            'bootstrap',
            [$container->get(BootstrapMiddleware::class), 'bootstrap']
        );
        // other attach here...

        return $eventManager;
    }),

    // other service definitions here...
];

We want the middleware executed in all application flow in all controller in the end? use ‘*’ and negative priority:

// config/di.php
use App\Middleware\AllEnderMiddleware;
use function DI\decorate;

return [
    'event_manager' => decorate(function($eventManager, $container) {

        $eventManager->attach(
            '*',
            [$container->get(AllEnderMiddleware::class), 'end'],
            -1
        );
        // other attach here...

        return $eventManager;
    }),

    // other service definitions here...
];

Wanna handle for specific controller’s action ? Use following usage:

// config/di.php
use App\Controller\IndexController;
use App\Middleware\IndexMiddleware;
use function DI\decorate;

return [

    'event_manager' => decorate(function($eventManager, $container) {

            // before ...
            $eventManager->attach(
                IndexController::class.'.index',
                [$container->get(IndexMiddleware::class), 'pre'],
                1
            );

            // after ...
            $eventManager->attach(
                IndexController::class.'.index',
                [$container->get(IndexMiddleware::class), 'post'],
                -1
            );
           // other attach here...

           return $eventManager;
    }),

    // other service definitions here...
];

If we use default Penny EventManager implementation, which is usage Zend Framework 2 EventManager, higher priority will be served first, lower priority will be served later.

If you are familiar with CakePHP, there is already a CakePHP Event implementation, that will serve lower priority first, higher later.

For callable listener, we may create listener service like the following:

namespace App\Middleware;

class IndexMiddleware
{
    public function pre($event)
    {
        $request = $event->getRequest();
        $response = $event->getResponse();

        // manipulate request or/and response here
        $request = $request->withAttribute('foo', 'fooValue');

        // apply manipulated request or/and response
        $event->setRequest($request);
        $event->setResponse($response);
    }

    public function post($event)
    {
        $request = $event->getRequest();
        $response = $event->getResponse();

        // manipulate request or/and response here
        $response = $response->withHeader('X-Powered-By', 'JAVA');

        // apply manipulated request or/and response
        $event->setRequest($request);
        $event->setResponse($response);
    }
}

We can then register the middleware in our Service Container:

//config/di.php
use App\Middleware\AllEnderMiddleware;
use App\Middleware\BootstrapMiddleware;
use App\Middleware\IndexMiddleware;
use function DI\object;

return [
    // ...
    AllEnderMiddleware::class => object(AllEnderMiddleware::class),
    BootstrapMiddleware::class => object(BootstrapMiddleware::class),
    IndexMiddleware::class => object(IndexMiddleware::class),
];

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out / Change )

Twitter picture

You are commenting using your Twitter account. Log Out / Change )

Facebook photo

You are commenting using your Facebook account. Log Out / Change )

Google+ photo

You are commenting using your Google+ account. Log Out / Change )

Connecting to %s

%d bloggers like this: