Spekkoek plugin for CakePHP
, (*1)
This plugin is a prototype for adding PSR7 middleware & request/response object
support to CakePHP. It should be considered experimental., (*2)
Concepts
Spekkoek aims to provide PSR7 middleware for a CakePHP 3.x application. It adds
a few new concepts to a CakePHP application that extend and enhance the existing abstractions., (*3)
-
Spekkoek\Application
The Application object provides an object oriented
approach to bootstrapping. This class is used to load bootstrapping and
application configuration. It also provides hook methods for configuring
middleware.
-
Spekkoek\MiddlewareStack
A MiddlewareStack provides an interface for
building and manipulating the stack of middleware. The Application
is also
a middleware object that helps encapsulate the existing CakePHP dispatch
process.
-
Spekkoek\Server
Is the entry point for a request/response. It consumes an
application, and returns a response. The server's emit() method can be used
to emit a response to the webserver SAPI.
There are PSR7 middleware versions of all the CakePHP core DispatchFilters.
These are intended to be long term replacements for the CakePHP dispatch
filters., (*4)
Middleware
Middleware is a closure or callable object that accepts a request/response and
returns a response. Each middleware is also provided the next callable in the chain.
This callable should be invoked if/when you want to delegate the response creation to the
next middleware object. Middleware objects need to implement the following protocol:, (*5)
public function __invoke($request, $response, $next)
Middleware objects must return a Response object. They can either augment the
existing response object or create a new one, or delegate to the next
middleware object by calling $next
. A trivial example of middleware would be:, (*6)
use Cake\Log\Log;
class TimingMiddleware
{
public function __invoke($request, $response, $next)
{
$start = microtime(true);
$response = $next($request, $response);
$end = microtime(true);
Log::info(sprintf(
'Request to %s took %f seconds',
$request->getUri()->getPath(),
($end - $start)
));
return $response;
}
}
Here we can see the $next
object in action and also how to put some simple
logic before and after the lower layers., (*7)
Usage
This plugin fundamentally reworks your application's bootstrap process. It
requires replacing your webroot/index.php
and implementing an Application
class., (*8)
Installation & Getting Started
Unlike many other plugins, Spekkoek requires a more setup. Because it needs to augment how
bootstrapping, requests and responses are handled you'll need to modify your webroot/index.php
, (*9)
Install the plugin with composer
:, (*10)
composer require "markstory/cakephp-spekkoek:dev-master"
Next update your webroot/index.php
to update, (*11)
Build the Application class
In your application's src
directory create src/Application.php
and put the following
in it:, (*12)
<?php
namespace App;
use Spekkoek\BaseApplication;
use Spekkoek\Middleware\AssetMiddleware;
use Spekkoek\Middleware\ErrorHandlerMiddleware;
use Spekkoek\Middleware\RoutingMiddleware;
class Application extends BaseApplication
{
public function middleware($middleware)
{
// Catch any exceptions in the lower layers,
// and make an error page/response
$middleware->push(new ErrorHandlerMiddleware());
// Handle plugin/theme assets like CakePHP normally does.
$middleware->push(new AssetMiddleware());
// Apply routing
$middleware->push(new RoutingMiddleware());
// The application is bound into the middleware
// stack by the Server
return $middleware;
}
}
Update webroot/index.php
With your Application
defined, you will need to update your
webroot/index.php
. It should look something like the following:, (*13)
require dirname(__DIR__) . '/vendor/autoload.php';
use Spekkoek\Server;
use App\Application;
// Bind your application to the server.
$server = new Server(new Application(dirname(__DIR__) . '/config'));
// Run the request/response through the application
// and emit the response.
$server->emit($server->run());