Middleware (MiddleWare)
How to quickly generate middleware?
Through the command line: Under the app/middleware directory Generate a Check middleware
php think make:middleware Check
Middleware code:
<?php namespace app\middleware; class Check { public function handle($request, \Closure $next) { if ($request->param('name') == 'think') { return redirect('index/think'); } return $next($request); } }
The entry execution method of the middleware must be the handle method, and the first parameter is the Request object, and the second parameter is a closure Bag.
The return value of the middleware handle method must be a Response object.
In this middleware, we perform redirection processing when we judge that the name parameter of the current request is equal to think. Otherwise, the request will be passed further to the application. To continue passing the request to the application, just call the callback function $next with $request as parameter.
Under certain requirements, you can use the third parameter to pass in additional parameters.
<?php namespace app\middleware; class Check { public function handle($request, \Closure $next, $name) { if ($name == 'think') { return redirect('index/think'); } return $next($request); } }
End scheduling
Middleware supports defining a callback mechanism before the request ends. You only need to add the end method in the middleware class.
public function end(\think\Response $response) { // 回调行为 }
Note that there cannot be any response output in the end method. Because the request response output has been completed when the callback is issued.
Pre/post middleware
Whether the middleware is executed before or after the specific operation is requested depends entirely on the definition of the middleware itself.
The following is a middleware for pre-behavior
<?php namespace app\middleware; class Before { public function handle($request, \Closure $next) { // 添加中间件执行代码 return $next($request); } }
The following is a middleware for post-behavior
<?php namespace app\middleware; class After { public function handle($request, \Closure $next) { $response = $next($request); // 添加中间件执行代码 return $response; } }
Middleware methods can also support dependency injection.
Let’s take a more practical example. We need to determine whether the current browser environment is WeChat or Alipay
namespace app\middleware; /** * 访问环境检查,是否是微信或支付宝等 */ class InAppCheck { public function handle($request, \Closure $next) { if (preg_match('~micromessenger~i', $request->header('user-agent'))) { $request->InApp = 'WeChat'; } else if (preg_match('~alipay~i', $request->header('user-agent'))) { $request->InApp = 'Alipay'; } return $next($request); } }
Then add a middleware.php file to your mobile version of the application
For example:/path/app/mobile/middleware.php
return [ app\middleware\InAppCheck::class, ];
Then in your controller you can get the relevant value through $this->request->InApp
Define the middleware alias
You can directly predefine the middleware in middleware.php in the application configuration directory (in fact, it is to add an alias identifier), for example:
return [ 'alias' => [ 'auth' => app\middleware\Auth::class, 'check' => app\middleware\Check::class, ], ];
can support the use of aliases Define a set of middleware, for example:
return [ 'alias' => [ 'check' => [ app\middleware\Auth::class, app\middleware\Check::class, ], ], ];
Registration middleware
The new version of middleware is divided into global middleware and application middleware ( There are four groups (valid in multi-application mode), routing middleware and controller middleware.
The execution order is: global gradually->application middleware->routing middleware->controller middleware
global middleware
Global middleware is defined in the middleware.php file under the app directory, using the following method:
<?php return [ \app\middleware\Auth::class, 'check', 'Hello', ];
The registration of middleware should use the complete class name, if the middleware alias has been defined (or grouping) can be used directly.
The execution order of global middleware is the definition order. Middleware parameters can be passed in when defining global middleware, and two methods are supported.
<?php return [ [\app\http\middleware\Auth::class, 'admin'], 'Check', ['hello','thinkphp'], ];
The above definition means that the admin parameter is passed to the Auth middleware and the thinkphp parameter is passed to the Hello middleware.
Application middleware
If you use multi-application mode, application middleware definition is supported. You can add the middleware.php file directly under the application directory. The definition method is the same as the global middleware definition, but it will only take effect under the application.
Routing middleware
The most commonly used middleware registration method is to register routing middleware
Route::rule('hello/:name','hello') ->middleware(\app\middleware\Auth::class);
Supports the registration of multiple middleware
Route::rule('hello/:name','hello') ->middleware([\app\middleware\Auth::class, \app\middleware\Check::class]);
You can directly predefine the middleware in middleware.php in the application configuration directory (actually, add an alias identifier), for example:
return [ 'auth' => app\middleware\Auth::class, 'check' => app\middleware\Check::class ];
Then use the middleware alias to register directly in the routing
Route::rule('hello/:name','hello') ->middleware(['auth', 'check']);
You can support using aliases to define a group of middleware, for example:
return [ 'check' => [ app\middleware\Auth::class, app\middleware\Check::class ], ];
Then, directly use the following method to register the middleware
Route::rule('hello/:name','hello') ->middleware('check');
Supports registering middleware for routing groups
Route::group('hello', function(){ Route::rule('hello/:name','hello'); })->middleware('auth');
Support middleware registration for a certain domain name
Route::domain('admin', function(){ // 注册域名下的路由规则 })->middleware('auth');
If you need to pass additional parameters to the middleware, you can use it
Route::rule('hello/:name','hello') ->middleware('auth', 'admin');
If you need to define multiple middlewares, use Array method
Route::rule('hello/:name','hello') ->middleware([Auth::class, 'Check']);
You can pass in the same extra parameter
Route::rule('hello/:name','hello') ->middleware(['auth', 'check'], 'admin');
or call it multiple times separately, specifying different parameters
Route::rule('hello/:name','hello') ->middleware('auth', 'admin') ->middleware('hello', 'thinkphp');
If you want a routing middleware to be Global execution (regardless of whether the route matches or not) does not need to be defined in the route. It can be defined directly in the routing configuration file. For example, add:
'middleware' => [ app\middleware\Auth::class, app\middleware\Check::class, ],
to the config/route.php configuration file. In this way, all applications All requests below will execute the Auth and Check middleware.
Use closures to define middleware
You don’t have to use middleware classes. In some simple situations, you can use closures to define middleware, but closures Package functions must return Response object instances.
Route::group('hello', function(){ Route::rule('hello/:name','hello'); })->middleware(function($request,\Closure $next){ if ($request->param('name') == 'think') { return redirect('index/think'); } return $next($request); });
Controller middleware
Supports defining middleware for controllers. You only need to define the middleware attribute in the controller, for example:
<?php namespace app\controller; class Index { protected $middleware = ['auth']; public function index() { return 'index'; } public function hello() { return 'hello'; } }
The auth middleware will be called when the index controller is executed, and the use of complete namespace definitions is also supported.
If you need to set the effective operation in the middle of the controller, you can define it as follows:
<?php namespace app\controller; class Index { protected $middleware = [ 'auth' => ['except' => ['hello'] ], 'check' => ['only' => ['hello'] ], ]; public function index() { return 'index'; } public function hello() { return 'hello'; } }
The middleware passes parameters to the controller
You can pass the request Pass parameters to the controller (or other places) by object assignment, such as
<?php namespace app\middleware; class Hello { public function handle($request, \Closure $next) { $request->hello = 'ThinkPHP'; return $next($request); } }
and then use
public function index(Request $request) { return $request->hello; // ThinkPHP }
execution priority# directly in the controller method.
##If you have strict requirements on the execution order of middleware, you can define the execution priority of middleware. Addreturn [ 'alias' => [ 'check' => [ app\middleware\Auth::class, app\middleware\Check::class, ], ], 'priority' => [ think\middleware\SessionInit::class, app\middleware\Auth::class, app\middleware\Check::class, ], ];
in the configuration file