Middleware
Overview
The Skinny framework implements a version of the Rack protocol. As a result, a Skinny application can have middleware that may inspect, analyze, or modify the application environment, request, and response before and/or after the Skinny application is invoked.
Middleware Architecture
Think of a Skinny application as the core of an onion. Each layer of the onion is middleware. When you invoke the Skinny application’s run() method, the outer-most middleware layer is invoked first. When ready, that middleware layer is responsible for optionally invoking the next middleware layer that it surrounds. This process steps deeper into the onion - through each middleware layer - until the core Skinny application is invoked. This stepped process is possible because each middleware layer, and the Skinny application itself, all implement a public call() method. When you add new middleware to a Skinny application, the added middleware will become a new outer layer and surround the previous outer middleware layer (if available) or the Skinny application itself.
Application Reference
The purpose of middleware is to inspect, analyze, or modify the application environment, request, and response before and/or after the Skinny application is invoked. It is easy for each middleware to obtain references to the primary Skinny application, its environment, its request, and its response:
<?php
class MyMiddleware extends \Skinny\Middleware
{
public function call()
{
//The Skinny application
$app = $this->app;
//The Environment object
$env = $app->environment;
//The Request object
$req = $app->request;
//The Response object
$res = $app->response;
}
}
Changes made to the environment, request, and response objects will propagate immediately throughout the application and its other middleware layers. This is possible because every middleware layer is given a reference to the same Skinny application object.
Next Middleware Reference
Each middleware layer also has a reference to the next inner middleware layer with $this->next. It is each middleware’s responsibility to optionally call the next middleware. Doing so will allow the Skinny application to complete its full lifecycle. If a middleware layer chooses not to call the next inner middleware layer, further inner middleware and the Skinny application itself will not be run, and the application response will be returned to the HTTP client as is.
<?php
class MyMiddleware extends \Skinny\Middleware
{
public function call()
{
//Optionally call the next middleware
$this->next->call();
}
}
How to Use
Use the Skinny application’s add() instance method to add new middleware to a Skinny application. New middleware will surround previously added middleware, or the Skinny application itself if no middleware has yet been added.
Example Middleware
This example middleware will capitalize the Skinny application’s HTTP response body.
<?php
class AllCapsMiddleware extends \Skinny\Middleware
{
public function call()
{
// Get reference to application
$app = $this->app;
// Run inner middleware and application
$this->next->call();
// Capitalize response body
$res = $app->response;
$body = $res->getBody();
$res->setBody(strtoupper($body));
}
}
Add Middleware
<?php
$app = \Skinny\Skinny::newInstance();
$app->add(new \AllCapsMiddleware());
$app->get('/foo', function () use ($app) {
echo "Hello";
});
$app->run();
The Skinny application’s add() method accepts one argument: a middleware instance. If the middleware instance requires special configuration, it may implement its own constructor so that it may be configured before it is added to the Skinny application.
When the example Skinny application above is run, the HTTP response body will be an enthusiastic “HELLO”;
How to Write
Skinny application middleware must subclass \Skinny\Middleware and implement a public call() method. The call() method does not accept arguments. Middleware may implement its own constructor, properties, and methods. I encourage you to look at Skinny’s built-in middleware for working examples (e.g. Skinny/Middleware/ContentTypes.php or Skinny/Middleware/SessionCookie.php).
This example is the most simple implementation of Skinny application middleware. It extends \Skinny\Middleware, implements a public call() method, and calls the next inner middleware.
<?php
class MyMiddleware extends \Skinny\Middleware
{
public function call()
{
$this->next->call();
}
}