首頁 >php框架 >ThinkPHP >TP5.1中間件在控制器中是如何使用的? (過程詳解)

TP5.1中間件在控制器中是如何使用的? (過程詳解)

藏色散人
藏色散人轉載
2022-01-13 11:09:102650瀏覽

下面thinkphp框架教學欄位將介紹給大家關於ThinkPHP5.1中間件在控制器中的使用過程,希望對需要的朋友有幫助!

ThinkPHP5.1中間件在控制器中使用過程

使用中間件的開始以及我的步驟描述,希望可以幫助才學php 或才學think框架的你們希望能夠與你們交流,讓自己進步。

中間件在Thinkphp框架中的作用我已經明白了,就是在請求即將達到應用層之前,對用戶訪問資源時候,產生的header頭或者用戶的請求參數時候輸入的post或get 或別的請求類型,以及url 路徑進行操作,其中包括了前置或後置操作或執行順序等方案。在理解後覺得這個東西在處理使用者請求資料的時候有極大的作用,比之直接在控制器或是在行為裡面處理好了很多。 (於是懷著滿滿的激動心情閱讀5.1的文件手冊)。

在閱讀完文件後,按照官方手冊的方法,在命令列中敲出如下程式碼:
php think make:middleware Check
這段程式碼的意思沒有任何問題就是生產一個中介軟體目錄以及建立一個新的名字為Check中間件文件
該內容正常完成沒有問題

按照文件要求方案貼上了5.1的文件代碼

TP5.1中間件在控制器中是如何使用的? (過程詳解)

完全照著手冊複製的,沒有任何問題,確認進行了保存以及任何錯誤。

在此確認在我的admin模組根目錄下放置了一個名字為middleware.php的檔案如下圖所示

TP5.1中間件在控制器中是如何使用的? (過程詳解)

#就這樣進行一個註冊,那麼這個模組下如果想使用中間件,就可以使用了。

然後我在控制器內按照文件手冊中的內容,根據控制器中間件內容描述加入如圖所示的程式碼

##,TP5.1中間件在控制器中是如何使用的? (過程詳解)

結果發現,代碼沒有被執行,納悶的我摸了摸腦袋,按照我的理解應,如果這麼做了的話,應該可以直接應用了才對的,結果對像是個空的。無奈下,按照自己的理解,我在中間件內停止了代碼

TP5.1中間件在控制器中是如何使用的? (過程詳解)

#在看到自己希望看到的內容後,再次測試我的$request。看到了我期待已久的東西,我的中間件好了

TP5.1中間件在控制器中是如何使用的? (過程詳解)

#至此以上步驟告訴我,第一步已經完成,我現在可以使用一個中間件做我想做的事情了

第一步先吧名字變成我想變得這裡有三處改動的地方。


TP5.1中間件在控制器中是如何使用的? (過程詳解)
TP5.1中間件在控制器中是如何使用的? (過程詳解)

TP5.1中間件在控制器中是如何使用的? (過程詳解)

#再刷新後發現依然可以使用,絕對溜溜的跑起來。在這一步驟中,也堅定了我的一些使用想法,例如創造多個中間件,每個控制器都應該有一個相對應的,在這裡執行一些自己象處理的,在看到手冊上還可以使用各種其他的方法,包括執行順序的改變,這讓我心中各種意淫。從此程式碼變得又可以稍微高大上一點了。

第二步驟建立功能規則配合Config配置中的自建文件,對存取進行控制

TP5.1中間件在控制器中是如何使用的? (過程詳解)

TP5.1中間件在控制器中是如何使用的? (過程詳解)

TP5.1中間件在控制器中是如何使用的? (過程詳解)

TP5.1中間件在控制器中是如何使用的? (過程詳解)

<?php namespace apphttpmiddleware;
use thinkfacadeConfig;
use thinkfacadeRequest;
/**
登陆接口通用数据配置检测*/
class AdminLoginCheck
{
/**
 * handle  重写处理请求对象的操作函数
 * @param  object Request $request 请求对象
 * @param  object \Closure $next 响应对象
 * @return array 错误返回的信息
 *         code 返回码
 *         msg 返回信息
 *         data 返回数据
 * @return  object 响应对象
 */
public function handle($request, \Closure $next)
{
    // 检测配置,查看该接口服务是否被暂停使用
    if (true !== Config::get(Request::module().&#39;.&#39;.Request::action().&#39;.&#39;.Request::action().&#39;_api&#39;))
    // 如果结果不符合要求则返回错误信息
    exit(json_encode([&#39;code&#39;=>1,'msg'=>'Interface_Pause_service','data'=>'']));
    // 检测配置,是否执行请求验证类型
    if (false !== Config::get(Request::module().'.'.Request::action().'.'.Request::action().'_request'))
    {

        // 登陆请求规则,传入相应方法,查看该接口是否符合请求类需
        $res = self::loginRequestRole(Request::action());
        // 如果结果不符合要求则返回错误信息
        if (true !== $res) exit(json_encode(['code'=>1,'msg'=>'Request_Type_Not_Matching','data'=>'']));
    }
    // 检测配置,是否执行地址限制验证
    if (false !== Config::get(Request::module().'.'.Request::action().'.'.Request::action().'_address'))
    {
        // 客户端访问地址限制请求规则
        $res = self::loginAddressDispose(Request::ip());
        // 如果结果不符合要求则返回错误信息
        if (true !== $res) exit(json_encode(['code'=>1,'msg'=>'Address_Not_Access','data'=>'']));
    }
    // 格式化与处理前台参数
    $request = self::loginParamDispose(Request::action(),$request);
    
    // 继续执行进入到控制器
    return $next($request);
}

/**
 * loginRequestRole 请求类型验证
 * @param  string $scene 根据路径传入方法名称
 * @return bool 验证用户访问的接口是否符合预设的请求要求
 */
protected static function loginRequestRole($scene)
{
    switch ($scene)
    {
        // 登陆页面请求验证
        case 'index':
            if (Request::isGet()) return true;
            else return false;
            break;
        // 登陆接口请求验证
        case 'login':
            if (Request::isPost() || Request::isAjax() || Request::isPjax()) return true;
            else return false;
            break;
        // 登陆接口请求验证
        case 'resetPassword':
            if (Request::isPost() || Request::isAjax() || Request::isPjax()) return true;
            else return false;
            break;
        // 默认验证或者不存在的场景返回
        default:
            return false;
            break;
    }
}

/**
 * loginAddressDispose 地址是否允许访问
 * @param  string $address 需要传入一个address地址
 * @return string     返回错误信息
 * @return bool     检测正确返回真
 */
protected static function loginAddressDispose($address)
{
    // 读取配置内的设置参数
    $data = Config::get(Request::module().'.'.Request::action().'.'.Request::action().'_address_data');
    // 如果配置信息address列表为空则返回不能访问
    if (empty($data)) return false;
    // 循环地址列表信息解开连续address地址列表
    foreach ($data as $key => $val) { if ($val == $address) return true; }
    // 如果继续执行下去依然没有 返回不能访问
    return false;
}

/**
 * loginParamDispose post内容与格式处理
 * @param  string $scene 需要前往的接口名称
 * @param  object $request 请求的对象内容
 * @return object 返回处理过的请求对象
 */
protected static function loginParamDispose($scene,$request)
{
    switch ($scene)
    {
        // 登陆页面
        case 'index':
            break;
        // 登陆接口请求参数处理
        case 'login':
            // 前台用户传入的参数进行调整转换
            $request->username = $request->param('user');
            $request->password = $request->param('pass');
            $request->captcha = $request->param('code');
            // 对记住我进行处理
            $remember = $request->param('remember');
            if (null === $remember) $request->remember = 'shut';
            else $request->remember = 'open';
            break;
        // 重置密码接口参数处理
        case 'resetPassword':
            // 前台用户传入的参数进行调整转换
            $request->username = $request->param('user');
            $request->phone = $request->param('mobile');
            $request->phonecode = $request->param('code');
            $request->password = $request->param('pass');
            $request->repassword = $request->param('repass');
            break;
        // 默认接口或者不存在的场景返回
        default:
            break;
    }
    return $request;
}
}

至此一個簡單的中間件偵測工作完成,當然,這種寫法是由固定要求的例如在多個控制存取中,介面的統一帶上api 請求的統一帶上request這樣不管怎麼樣都可以正常使用

單獨要說的兩個問題,就是其實可以將配置中需要用到的內容繼續進行

第一個問題是中間件並不是萬能的,只能做一些請求處理,而且是必須帶參的,千萬不要去做不符合要求的高級驗證,這裡最多的只是做一些前置驗證,讓數據安全或讓資料飽滿

第二給問題是不要在中間件中嘗試做不合時宜的動作,不要在中間件中執行超級複雜的程式碼,如果你拿中間件做超級複雜的程式碼或超長運算,我估計可以坑死很多人,這裡所說包括了盡量少使用自己函數庫定義的函數代碼驗證有些避不開的還是可以使用的,比如密碼加密這種類似的代碼

以上是TP5.1中間件在控制器中是如何使用的? (過程詳解)的詳細內容。更多資訊請關注PHP中文網其他相關文章!

陳述:
本文轉載於:segmentfault.com。如有侵權,請聯絡admin@php.cn刪除