玩啦 2年多的 laravel 最近才注意到 laravel 的中间件还有后置的;
之前我理解的中间件都是在请求之前做的一些逻辑判断;
那么后置中间件可以做一些什么呢?
1:统计记录API的响应时间,请求参数和响应值;
2:后台的一些操作记录;
......等等;
有了后置中间件;
对于我们处理某些业务会方便许多;
其实很简单;
Laravel 的中间件有一个叫做 terminate
的方法;
如果我们在中间件里面加上了该方法;
那么在 Laravel 整个生命周期执行快要结束的时候;
Laravel 就会执行这个方法,方法结构如下:
注意 : 中间件必须存在与你应该将它添加到 app/Http/Kernel.php
;全局中间件
中。
public function terminate($request, $response)
{
//编写业务逻辑
}
那Laravel 具体是怎么实现的呢?
这个嘛;
还需要追溯到Laravel的根目录 public/index.php
;
大概是60行左右;
/*
|--------------------------------------------------------------------------
| Run The Application
|--------------------------------------------------------------------------
|
| Once we have the application, we can handle the incoming request
| through the kernel, and send the associated response back to
| the client's browser allowing them to enjoy the creative
| and wonderful application we have prepared for them.
|
*/
$kernel = $app->make(Illuminate\Contracts\Http\Kernel::class);
$response = $kernel->handle(
$request = Illuminate\Http\Request::capture()
);
$response->send(); //给浏览器响应数据
$kernel->terminate($request, $response); //调用后置中间件
然后会去调用Laravel底层代码;
调用最关键的一个方法api\vendor\laravel\framework\src\Illuminate\Foundation\Http\Kernel.php
里面的terminateMiddleware() 方法;
/**
* Call the terminate method on any terminable middleware.
*
* @param \Illuminate\Http\Request $request
* @param \Illuminate\Http\Response $response
* @return void
*/
protected function terminateMiddleware($request, $response)
{
$middlewares = $this->app->shouldSkipMiddleware() ? [] : array_merge(
$this->gatherRouteMiddleware($request),
$this->middleware
);
foreach ($middlewares as $middleware) {
if (! is_string($middleware)) {
continue;
}
list($name) = $this->parseMiddleware($middleware);
Log::info("中间件名称 =============== ",[$name]);
$instance = $this->app->make($name);
if (method_exists($instance, 'terminate')) {
$instance->terminate($request, $response);
}
}
}
我们直接上代码;
定义中间件如下;
注意: 中间件必须定义在全局中间件
中;
重要的事情说三遍 (╥╯^╰╥);
<?php
namespace App\Http\Middleware;
use Closure;
use Illuminate\Support\Facades\Log;
class AdminAuth
{
/**
* Handle an incoming request.
*
* @param \Illuminate\Http\Request $request
* @param \Closure $next
* @return mixed
*/
public function handle($request, Closure $next){
Log::info('经过了前置中间件');
return $next($request);
}
/**
* @param $request
* @param $response
* @
*/
public function terminate($request, $response){
// 编写业务逻辑
Log::info('经过了后置中间件');
}
}
然后我们执行一下代码;
查看日志;
[2019-10-20 19:45:44] local.INFO: 经过了前置中间件
[2019-10-20 19:45:45] local.INFO: 中间件名称 =============== ["App\\Http\\Middleware\\EncryptCookies"]
[2019-10-20 19:45:45] local.INFO: 中间件名称 =============== ["Illuminate\\Cookie\\Middleware\\AddQueuedCookiesToResponse"]
[2019-10-20 19:45:45] local.INFO: 中间件名称 =============== ["Illuminate\\Session\\Middleware\\StartSession"]
[2019-10-20 19:45:45] local.INFO: 中间件名称 =============== ["Illuminate\\View\\Middleware\\ShareErrorsFromSession"]
[2019-10-20 19:45:45] local.INFO: 中间件名称 =============== ["App\\Http\\Middleware\\VerifyCsrfToken"]
[2019-10-20 19:45:45] local.INFO: 中间件名称 =============== ["Illuminate\\Routing\\Middleware\\SubstituteBindings"]
[2019-10-20 19:45:45] local.INFO: 中间件名称 =============== ["Illuminate\\Foundation\\Http\\Middleware\\CheckForMaintenanceMode"]
[2019-10-20 19:45:45] local.INFO: 中间件名称 =============== ["Illuminate\\Foundation\\Http\\Middleware\\ValidatePostSize"]
[2019-10-20 19:45:45] local.INFO: 中间件名称 =============== ["App\\Http\\Middleware\\TrimStrings"]
[2019-10-20 19:45:45] local.INFO: 中间件名称 =============== ["Illuminate\\Foundation\\Http\\Middleware\\ConvertEmptyStringsToNull"]
[2019-10-20 19:45:45] local.INFO: 中间件名称 =============== ["App\\Http\\Middleware\\TrustProxies"]
[2019-10-20 19:45:45] local.INFO: 中间件名称 =============== ["App\\Http\\Middleware\\EnableCrossRequestMiddleware"]
[2019-10-20 19:45:45] local.INFO: 中间件名称 =============== ["App\\Http\\Middleware\\Cors"]
[2019-10-20 19:45:45] local.INFO: 中间件名称 =============== ["App\\Http\\Middleware\\TrimStrings"]
[2019-10-20 19:45:45] local.INFO: 中间件名称 =============== ["App\\Http\\Middleware\\AdminAuth"] //我们刚刚定义的中间件
[2019-10-20 19:45:45] local.INFO: 经过了后置中间件
最后会判断中间件类里面是否存在 terminate
方法;
存在执行方法里面的逻辑;
๑乛◡乛๑ 后置中间件的实现方式;
大概就是这样;
最后送上开胃小菜;
在某种情况下,你可能需要中间件以特定的顺序执行;
但是当它们被分配到路由时;
你无法控制它们的顺序。
在这种情况下,可以使用 app/Http/Kernel.php 文件的排序中间件;
/**
* 中间件的优先级排序列表
*
* 将会强制非全局中间件始终保持给定的顺序。
*
* @var array
*/
protected $middlewarePriority = [
\Illuminate\Session\Middleware\StartSession::class,
\Illuminate\View\Middleware\ShareErrorsFromSession::class,
\App\Http\Middleware\Authenticate::class,
\Illuminate\Session\Middleware\AuthenticateSession::class,
\Illuminate\Routing\Middleware\SubstituteBindings::class,
\Illuminate\Auth\Middleware\Authorize::class,
];
app/Http/Kernel.php 的 $middlewarePriority 属性对应着
对应着 api\vendor\laravel\framework\src\Illuminate\Foundation\Http\Kernel.php 的 $middlewarePriority 属性
;
$middlewarePriority 属性指定中间件优先级
一一对应的;
这是意外收获;
备注:
需要使用 laravel
内置的函数 response()
返回响应:
/**
* @param int $code
* @param string $msg
* @param string $data
* @param bool $page
* @return \Illuminate\Http\JsonResponse
* @author shidatuo
* @description 返回json数据
*/
function jsonReturn($code = 0, $msg='', $data='', $page = false){
if(empty($data))
$data = [];
if(!$page)
return response()->json(compact('code','msg','data'));
$rs = ['code' => $code];
$rs += ['msg' => $msg];
$rs += $data;
return response()->json($rs);
}
本文为史大坨原创文章,转载无需和我联系,但请注明来自史大坨博客https://www.shidatuos.cn