PHP code example of itantik / middleware

1. Go to this page and download the library: Download itantik/middleware library. Choose the download type require.

2. Extract the ZIP file and open the index.php.

3. Add this code to the index.php.
    
        
<?php
require_once('vendor/autoload.php');

/* Start to develop here. Best regards https://php-download.com/ */

    

itantik / middleware example snippets


class LoggableRequest implements IRequest
{
    /** @var string[] */
    private $logs = [];

    public function addLog(string $message): void
    {
        $this->logs[] = $message;
    }

    /**
     * @return string[]
     */
    public function getLogs(): array
    {
        return $this->logs;
    }
}

class LoggableResponse implements IResponse
{
    /** @var string[] */
    private $logs = [];

    public function addLog(string $message): void
    {
        $this->logs[] = $message;
    }

    /**
     * @return string[]
     */
    public function getLogs(): array
    {
        return $this->logs;
    }
}

class FirstMiddleware implements IMiddleware
{
    public function handle(IRequest $request, ILayer $nextLayer): IResponse
    {
        // do something BEFORE next middleware
        if ($request instanceof LoggableRequest) {
            $request->addLog('FirstMiddleware begin');
        }

        // MUST invoke next middleware
        $resp = $nextLayer->handle($request);

        // do something AFTER next middleware
        if ($resp instanceof LoggableResponse) {
            $resp->addLog('FirstMiddleware end');
        }

        // MUST return response
        return $resp;
    }
}

class SecondMiddleware implements IMiddleware
{
    public function handle(IRequest $request, ILayer $nextLayer): IResponse
    {
        // here do nothing BEFORE next middleware

        // MUST invoke next middleware
        $resp = $nextLayer->handle($request);

        // do something AFTER next middleware
        if ($resp instanceof LoggableResponse) {
            $resp->addLog('SecondMiddleware end');
        }

        // MUST return response
        return $resp;
    }
}

class TransactionalMiddleware implements IMiddleware
{
    /** @var Connection */
    private $connection;

    public function __construct(Connection $connection)
    {
        $this->connection = $connection;
    }

    public function handle(IRequest $request, ILayer $nextLayer): IResponse
    {
        $connection = $this->connection;

        // begin database transaction
        $connection->beginTransaction();

        try {
            // invoke next middleware
            $resp = $nextLayer->handle($request);

            // commit database transaction
            $connection->commit();
        } catch (Exception $e) {
            // rollback database transaction
            $connection->rollback();
            throw $e;
        }

        // return response
        return $resp;
    }
}

class CoreLayer implements ILayer
{
    public function handle(IRequest $request): IResponse
    {
        if ($request instanceof LoggableRequest) {
            $request->addLog('CoreLayer begin');
        }

        // create response
        $resp = new LoggableResponse();
        $resp->addLog('CoreLayer end');

        // return response
        return $resp;
    }
}

// create middleware manager
$manager = new \Itantik\Middleware\Manager();

// register middlewares
$manager->append(new FirstMiddleware());
$manager->append(new SecondMiddleware());

// create request
$request = new LoggableRequest();

// create core layer for this request
$coreLayer = new CoreLayer();

// run it
$response = $manager->process($request, $coreLayer);

// expected result
$requestLogs = $request->getLogs();
// [
//    'FirstMiddleware begin',
//    'CoreLayer begin',
// ]
$responseLogs = $response->getLogs();
// [
//    'CoreLayer end',
//    'SecondMiddleware end',
//    'FirstMiddleware end',
// ]

// now we can take another request with appropriate core layer that handles it
// and run middleware manager again
$response = $manager->process($anotherRequest, $anotherLayer);
// and again

// transport layer object
class DataTransportLayer implements ILayer
{
    /** @var IMiddleware */
    private $middleware;
    /** @var ILayer */
    private $nextLayer;

    public function __construct(IMiddleware $middleware, ILayer $nextLayer)
    {
        $this->middleware = $middleware;
        $this->nextLayer = $nextLayer;
    }

    /**
     * @param IRequest $request
     * @return IResponse
     * @throws MiddlewareException
     */
    public function handle(IRequest $request): IResponse
    {
        $res = $this->middleware->handle($request, $this->nextLayer);

        // check a correct response type returned from each middleware handler
        if (!($res instanceof DataResponse)) {
            throw new MiddlewareException(
                sprintf("Middleware handler must return an instance of '%s'.", DataResponse::class)
            );
        }
        return $res;
    }
}

// transport layer factory
class DataTransportLayerFactory implements ITransportLayerFactory
{
    public function create(IMiddleware $middleware, ILayer $nextLayer): ILayer
    {
        return new DataTransportLayer($middleware, $nextLayer);
    }
}

// add transport layer factory to the manager
$manager = new \Itantik\Middleware\Manager(new DataTransportLayerFactory());