在THINKPHP中,排除某些操作跳过中间件的一些思路

需求:希望在多应用下,在指定的某个应用中,使用了中间件做类似登录检测的时候,应用下的某些操作,可以跳过这个中间件。

例如:api 应用的 login 这个控制器下下面有几个操作,例如 info,login,logout、other

对应的路径分别是 api/login/info、api/login/login、api/login/logout、api/login/other、但是我们想对 api/login/other 这个操作跳过中间件检查。

Thinkphp中,可以用的中间件有 全局中间件、应用中间件、路由中间件、控制器中间件

其实控制器中间件,大概可以支持这个需求,看官方文档:

如果需要设置控制器中间的生效操作,可以如下定义:

<?php
namespace app\controller;


class Index
{
    protected $middleware = [ 
    	'auth' 	=> ['except' 	=> ['hello'] ],//---这里是排除的操作执行中间件
        'check' => ['only' 		=> ['hello'] ],//---这里是仅仅某个操作执行中间件
    ];

    public function index()
    {
        return 'index';
    }

    public function hello()
    {
        return 'hello';
    }
}

由于项目需要在中间件中根据输入的值进行简单处理或,把用户id作为传递值提交给控制器,然后在控制器中 在 __construct 获取由中间件的传递的值,并进行初始化操作。

但在使用过程中发现,如果使用控制中间件,无法在中间件传值,原因参考这里:CSDNicon-default.png?t=N7T8https://mp.csdn.net/mp_blog/creation/editor/134923605

转而使用  应用中间件,但是在应用控制中,传值是可以传值了,但是我需要在应用的某个操作中,要跳过控制器,所以需要在控制器中获取到 当前控制器和当前操作

#当前控制器
    $controller = $request->controller();
    #当前操作
    $action = $request->action();

但在应用控制器中,无法获得当前控制器的值、当前操作值,总之上面两个是没办法获取到值的。

原本想尝试用路由中间件,可是无论如何定义路由,在多应用中,如果我只是想排除某个操作跳过中间件检测,操作起来还是比较麻烦的

最后测试了一下,发现路由中间件可以满足。

在THINKPHP的官方文档中提到:

如果你希望某个路由中间件是全局执行(不管路由是否匹配),可以不需要在路由里面定义,支持直接在路由配置文件中定义,例如在config/route.php配置文件中添加:

'middleware'    =>    [
    app\middleware\Auth::class,
    app\middleware\Check::class,
],

这样,所有该应用下的请求都会执行AuthCheck中间件。

我们可以把这个全局路由中间件,作为某个应用下的全局中间件,只在作用在某个应用下。具体操作如下:

第一步:在某个应用下,例如api下新建一个 config文件夹,然后新建 route.php文件

route.php文件内容大致是这样:

<?php
return [
  //路由中间件
  'middleware' => [
    \app\api\middleware\Check::class, // 检测状态
  ],
];

这样,这个应用下,都会运行这个中间件。接下来我们要排除掉某些操作

在这个应用的某个控制器下,定义一个公共变量 skipMiddleware  ,代码片段大致如下

<?php
declare (strict_types = 1);

namespace app\api\controller;

use think\Request;

class Index
{
  //跳过中间件检测的action,
  public $skipMiddleware = ['index']; //--》这里定义了一个跳过中间件的数组,数组的成员名称,就是你要跳过的操作名称
  //public $onlyMiddleware = ['index'];

//balabababa 
//balabababa 主代码部分省略
//balabababa 

}

然后我们在中间件中处理一下逻辑,代码大致如下

<?php
#中间件
namespace app\api\middleware;

class Check
{
  public function handle($request, \Closure $next)
  {
    #获取当前应用
    $appname = app('http')->getName();
    #当前控制器
    $controller = $request->controller();
    #当前操作
    $action = $request->action();
    
    #自动定位到控制器,取出设置的变量
    $class = "\app\\{$appname}\controller\\{$controller}";
    $model = new $class($request);
    
    #跳过中间件的设置
    if(
        property_exists($model, 'skipMiddleware') 
        && 
        $model->skipMiddleware 
        && 
       in_array($action,$model->skipMiddleware)
     ){
      return $next($request);
    };
    
//没跳过部分的代码略

上面是实现了指定某些操作下,跳过中间件检查。

  • 24
    点赞
  • 21
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值