Steven Maguire
I've been building web software since 2004.
general term for software that serves to "glue together" separate, often complex and already existing, programs
bit.ly/middleware-definition
bit.ly/middleware-in-books
Inbound middleware
Application
Outbound middleware
(very)
^
Pre-PSR 7 PHP
Pre-PSR 7 PHP
php-fig.org
It's kind of like the United Nations of PHP
Let's design widely accepted interfaces for HTTP Requests and HTTP Responses and use them in our projects!
Post-PSR 7 PHP
SAME
API
!!!
<?php namespace App\Http\Middleware;
use Psr\Http\Message\RequestInterface;
class MyMiddleware
{
/**
* Handle request.
* @param Psr\Http\Message\RequestInterface $request
* @return Psr\Http\Message\RequestInterface
*/
public function doThatSweetMagic(RequestInterface $request)
{
// Do something awesome to the request
return $request;
}
}
laravel.com/docs/5.1/middleware
Any class that implements a public method named handle that accepts a Request object, a Closure object, and returns a Response object
/**
* @param Request $request
* @param Closure $next
*
* @return Response
*/
public function handle($request, Closure $next);
"chained"
The hard part is done for you.
<?php
namespace App\Http\Middleware;
use Closure;
class MyVeryOwnMiddleware
{
public function handle($request, Closure $next)
{
// Perform action
return $next($request);
}
}
<?php
namespace App\Http\Middleware;
use Closure;
class BeforeMiddleware
{
public function handle($request, Closure $next)
{
// Perform action
return $next($request);
}
}
<?php
namespace App\Http\Middleware;
use Closure;
class AfterMiddleware
{
public function handle($request, Closure $next)
{
$response = $next($request);
// Perform action
return $response;
}
}
Any Middleware class that implements a public method named terminate that accepts a Request object, a Response object, and has no return
<?php
namespace Illuminate\Session\Middleware;
use Closure;
class StartSession
{
public function handle($request, Closure $next)
{
return $next($request);
}
public function terminate($request, $response)
{
// Store the session data...
}
}
// app/Http/Kernel.php
<?php
namespace App\Http;
use Illuminate\Foundation\Http\Kernel as HttpKernel;
class Kernel extends HttpKernel
{
/**
* The application's global HTTP middleware stack.
*
* @var array
*/
protected $middleware = [];
/**
* The application's route middleware.
*
* @var array
*/
protected $routeMiddleware = [];
}
// Within App\Http\Kernel Class...
protected $middleware = [
\Illuminate\Foundation\Http\Middleware\CheckForMaintenanceMode::class,
\App\Http\Middleware\EncryptCookies::class,
\Illuminate\Cookie\Middleware\AddQueuedCookiesToResponse::class,
\Illuminate\Session\Middleware\StartSession::class,
\Illuminate\View\Middleware\ShareErrorsFromSession::class,
\App\Http\Middleware\VerifyCsrfToken::class,
\App\Http\Middleware\MyMiddleware::class,
];
// Within App\Http\Kernel Class...
protected $routeMiddleware = [
'auth' => \App\Http\Middleware\Authenticate::class,
'auth.basic' => \Illuminate\Auth\Middleware\AuthenticateWithBasicAuth::class,
'guest' => \App\Http\Middleware\RedirectIfAuthenticated::class,
'mine' => \App\Http\Middleware\MyMiddleware::class,
];
Requires unique key, used as reference in other parts of application
will always execute and in the order registered within the Kernel
// Within app/Http/Kernel.php
protected $middleware = [
//
\App\Http\Middleware\MyMiddleware1::class,
\App\Http\Middleware\MyMiddleware2::class,
\App\Http\Middleware\MyMiddleware3::class,
//
];
Multiple middleware executed globally
// MyMiddleware1 executed
// MyMiddleware2 executed
// MyMiddleware3 executed
// Within app/Http/Kernel.php
protected $middleware = [
//
\App\Http\Middleware\MyMiddleware2::class,
\App\Http\Middleware\MyMiddleware3::class,
\App\Http\Middleware\MyMiddleware1::class,
//
];
Multiple middleware executed globally
// MyMiddleware2 executed
// MyMiddleware3 executed
// MyMiddleware1 executed
can be assigned to routes, route groups, and controllers, which will control execution order
// Within app/Http/Kernel.php
protected $routeMiddleware = [
//
'mine' => \App\Http\Middleware\MyMiddleware::class,
//
];
// Within app/Http/routes.php
Route::get('profile', ['middleware' => 'mine', function () {
//
}]);
Single middleware executed by route
// MyMiddleware executed
// Within app/Http/Kernel.php
protected $routeMiddleware = [
//
'mine.one' => \App\Http\Middleware\MyMiddleware1::class,
'mine.two' => \App\Http\Middleware\MyMiddleware2::class,
'mine.three' => \App\Http\Middleware\MyMiddleware3::class,
//
];
// Within app/Http/routes.php
Route::get('profile', ['middleware' => [
'mine.one','mine.two','mine.three'], function () {
//
}]);
Multiple middleware executed by route
// MyMiddleware1 executed
// MyMiddleware2 executed
// MyMiddleware3 executed
// Within app/Http/Kernel.php
protected $routeMiddleware = [
//
'mine.one' => \App\Http\Middleware\MyMiddleware1::class,
'mine.two' => \App\Http\Middleware\MyMiddleware2::class,
'mine.three' => \App\Http\Middleware\MyMiddleware3::class,
//
];
// Within app/Http/routes.php
Route::get('profile', ['middleware' => [
'mine.two','mine.three','mine.one'], function () {
//
}]);
Multiple middleware executed by route
// MyMiddleware2 executed
// MyMiddleware3 executed
// MyMiddleware1 executed
// Within app/Http/Kernel.php
protected $routeMiddleware = [
//
'mine.one' => \App\Http\Middleware\MyMiddleware1::class,
'mine.two' => \App\Http\Middleware\MyMiddleware2::class,
'mine.three' => \App\Http\Middleware\MyMiddleware3::class,
//
];
// Within app/Http/routes.php
Route::group(['middleware' => ['mine.two','mine.three','mine.one']], function () {
Route::get('profile', function () {
//
});
});
Multiple middleware executed by route group
// MyMiddleware2 executed
// MyMiddleware3 executed
// MyMiddleware1 executed
// Within app/Http/Kernel.php
protected $routeMiddleware = [
//
'mine.one' => \App\Http\Middleware\MyMiddleware1::class,
'mine.two' => \App\Http\Middleware\MyMiddleware2::class,
'mine.three' => \App\Http\Middleware\MyMiddleware3::class,
//
];
// Within app/Http/routes.php
Route::get('profile', 'MainController@profile');
// Within app/Http/Controllers/MainController.php
public function __construct()
{
$this->middleware('mine.two');
$this->middleware('mine.three');
$this->middleware('mine.one');
}
Multiple middleware executed by controller
// MyMiddleware2 executed
// MyMiddleware3 executed
// MyMiddleware1 executed
// Within app/Http/routes.php
Route::get('hello', 'MainController@hello');
Route::get('goodbye', 'MainController@goodbye');
// Within app/Http/Controllers/MainController.php
public function __construct()
{
$this->middleware('mine.two');
$this->middleware('mine.three');
$this->middleware('mine.one');
}
public function hello()
{
return 'hello';
}
public function goodbye()
{
return 'goodbye';
}
Multiple middleware executed by controller
// MyMiddleware2 executed
// MyMiddleware3 executed
// MyMiddleware1 executed
// MyMiddleware2 executed
// MyMiddleware3 executed
// MyMiddleware1 executed
// Within app/Http/routes.php
Route::get('hello', 'MainController@hello');
Route::get('goodbye', 'MainController@goodbye');
// Within app/Http/Controllers/MainController.php
public function __construct()
{
$this->middleware('mine.two', ['only' => ['hello']]);
$this->middleware('mine.three', ['except' => ['hello']]);
$this->middleware('mine.one');
}
public function hello()
{
return 'hello';
}
public function goodbye()
{
return 'goodbye';
}
Multiple middleware executed by controller
// MyMiddleware2 executed
// MyMiddleware1 executed
// MyMiddleware3 executed
// MyMiddleware1 executed
can be passed parameters!
// Within app/Http/Kernel.php
protected $routeMiddleware = [
//
'mine' => \App\Http\Middleware\MyMiddleware::class,
//
];
// Within app/Http/routes.php
Route::get('profile', ['middleware' => 'mine:foo', function () {
//
}]);
// Within app/Http/Controllers/MainController.php
public function __construct()
{
$this->middleware('mine:bar');
}
Pass single parameter to route middleware
// Within app/Http/Kernel.php
protected $routeMiddleware = [
//
'mine' => \App\Http\Middleware\MyMiddleware::class,
//
];
// Within app/Http/routes.php
Route::get('profile', ['middleware' => 'mine:foo,bar', function () {
//
}]);
// Within app/Http/Controllers/MainController.php
public function __construct()
{
$this->middleware('mine:bar,foo');
}
Pass multiple parameters to route middleware
Receive middleware parameters
// Within app/Http/Middleware/BeforeMiddleware.php
public function handle($request, Closure $next, $param1, $param2)
{
\Log::info($param1);
\Log::info($param2);
// Perform action
return $next($request);
}
// Within app/Http/routes.php
Route::get('profile', ['middleware' => 'mine:foo,bar', function () { }]);
// local.INFO: foo
// local.INFO: bar
Middleware parameters may be required or optional
// Within app/Http/Middleware/BeforeMiddleware.php
public function handle($request, Closure $next, $param1, $param2)
{
\Log::info($param1);
\Log::info($param2);
// Perform action
return $next($request);
}
// Within app/Http/routes.php
Route::get('profile', ['middleware' => 'mine:foo', function () { }]);
// ErrorException in BeforeMiddleware.php line 16:
// Missing argument 4 for App\Http\Middleware\BeforeMiddleware::handle()
Middleware parameters may be required or optional
// Within app/Http/Middleware/BeforeMiddleware.php
public function handle($request, Closure $next, $param1, $param2 = null)
{
\Log::info($param1);
\Log::info($param2);
// Perform action
return $next($request);
}
// Within app/Http/routes.php
Route::get('profile', ['middleware' => 'mine:foo', function () { }]);
// local.INFO: foo
// local.INFO:
github.com/stevenmaguire/middle-earth-ware
(bit.ly/laravel-middleware-demo)
@stevenmaguire
on twitter
stevenmaguire@gmail.com
on electronic mail
stevenmaguire
on github
By Steven Maguire
Deck originally created for a presentation to a gathering of the Chicago Laravel Meetup group - bit.ly/laravel-middleware