官方文档:
https://learnku.com/docs/laravel/7.x/middleware/7459
laravel 中间件
中间件默认存放在 app\http\middleware 目录下
中间件是做什么?
是处理请求判断的,
如果是 则真 继续执行 如果false 则停止。
使用场景:
如果这些所有if else 写在业务代码中,呵呵 则越来越多 越来越乱 最后难以维护。
中间件可以为我们解决这个难题。
中间件分两种:
全局中间件
路由中间件
先看一下中间件怎么写:
First.php 先写第一个中间件: age不能==200 其他请求过,只有200 会拦截。
namespace App\Http\Middleware;
use Closure;
class First {
public function handle($request, Closure $next) {
if ($request->input('age') == 200) {
echo 'age 不能等于200';
exit;
}
return $next($request);
}
}
第一个中间件就写完了。你可以举一反三,比如验证是否ajax() 请求,如果是则 返回header头信息。
第二步:中间件如何使用?
1、全局中间件使用
lumen 在 bootstarp/app.php 中
$app->middleware([
App\Http\Middleware\First::class,
App\Http\Middleware\Second::class,
]);
注册到了全局中,任何请求都会执行到两个中间件。
执行的顺序,使用注册顺序
$router->get('user/tt','UserController@tt');
查看日志
[2018-07-23 14:47:07] lumen.INFO: first middleware 1532328427.5392
[2018-07-23 14:47:07] lumen.INFO: Second middleware 中间件e 1532328427.5402
//如果这里也定义了 中间件会走两遍
$router->get('user/tt', ['middleware' =>'routemiddle', 'uses' => 'UserController@tt']);
查看日志
[2018-07-23 14:47:07] lumen.INFO: first middleware 1532328427.5392
[2018-07-23 14:47:07] lumen.INFO: Second middleware 中间件e 1532328427.5402
[2018-07-23 14:47:07] lumen.INFO: RouteMiddle 1532328427.5412
这是中间件执行的过程,按照顺序执行的。
2、路由中间件使用(其他地不使用)
再来看看这种写法,这叫路由写法
看到中间件使用的是routemiddle 这是一个字符串,那么为什么会能使用呢?
$router->get('user/tt',['middleware'=>'routemiddle','uses'=>'UserController@tt']);
当然也可以这样写:
$router->get('user/tt',['middleware'=>App\Http\Middleware\RouteMiddle::class,'uses'=>'UserController@tt']);
看这里:bootstrap/app.php
有这么一行代码: 注册了路由名 ,但程序并不默认执行。
$app->routeMiddleware([
'routemiddle' => App\Http\Middleware\RouteMiddle::class,
]);
public function handle($request, Closure $next)
要让请求继续传递到应用程序中(即允许「通过」中间件验证的),只需使用 $request 作为参数去调用回调函数 $next
前置 & 后置中间件
中间件是在请求之前或之后运行取决于中间件本身。例如, 接下来的这个中间件将在应用处理请求 之前 执行其任务
class BeforeMiddleware
{
public function handle($request, Closure $next)
{
// Perform action
return $next($request);
}
}
而接下来的这个中间件将在应用处理请求 之后 执行其任务:(处理请求之后触发 )
class AfterMiddleware
{
public function handle($request, Closure $next)
{
$response = $next($request);
// 执行操作 先执行的response 然后再返回的,这就是后置执行
return $response;
}
}
中间件中只有一个方法,就是handle() 。可以在这里执行相对应的执行和判断。
我们处理的请求一般是:加减密 、cros跨域 、 请求拦截、错误信息拦截、
传递参数给中间件
附加的中间参数会在 $next 参数之后传递给中间件:
定义路由时通过一个 : 来隔开中间件名称和参数来指定中间件参数。多个参数就使用逗号分隔:
如果多个参数使用逗号分隔
'login_check_info:2,login'
Route::middleware(['login_check_info:2'])->group(function () {
});class LoginCheckInfo
{
public $expire = 300; //5分钟过期
/**
*
* handle
* @param Request $request
* @param Closure $next
* @param $accountType //账号类型 1:药师,2:管理员
* @return mixed
* @throws ApiException
* @throws \Psr\SimpleCache\InvalidArgumentException
*
* @date 2020/3/16 11:31
*/
public function handle(Request $request, Closure $next, $accountType)
{
$openId = $request->header('BHC-GATEWAY-OPEN-ID', '');
if ($pharmacist['accountType'] != $accountType) {
//取反操作
if ($accountType == 2) {
throw new ApiException('此账号为药师账号,请更换为管理员账号', StatusCode::CHANGE_ACCOUNT_MANAGER);
}
if ($accountType == 1) {
throw new ApiException('此账号为管理员账号,请更换为药师账号', StatusCode::CHANGE_ACCOUNT_PHARMACIST);
}
}
return $next($request);
}
}中间件支持匿名函数写法
Route::middleware(['login_check_info'])->middleware(
function( $request, $next){
\Illuminate\Support\Facades\Log::info('test');
return $next($request);
})->group(function () {
});中间件传递参数到控制器
方式1
中间件
class MidParams //中间件
{
public function handle($request, Closure $next)
{
$mid_params = ['mid_params'=>'this is mid_params'];
$request->attributes->add($mid_params);//添加参数
return $next($request);//进行下一步(即传递给控制器)
}
}控制器
//注意:$request->attributes->add这种方法 input()取不到值 只能用get('xxx')取到值
class MidController extends Controller { //控制器
public function testMidFunc(Request $request) {
$input_params = $request->input();//获取参数
$mid_params = $request->get('mid_params');//中间件产生的参数
return ['my_params'=>$input_params,
'mid_params'=>$mid_params];
//注意:$request->attributes->add这种方法 input()取不到值 只能用get('xxx')取到值
}
}方式2
中间件
class MidParams //中间件
{
public function handle($request, Closure $next)
{
$mid_params = ['mid_params'=>'this is mid_params'];
$request->merge($mid_params);//合并参数
return $next($request);
}
}控制器
class MidController extends Controller { //控制器
public function testMidFunc(Request $request) {
$all_params = $request->input();//获取参数
return ['all_params'=>$all_params];
}
}