簡(jiǎn)化 Laravel 路由功能

Laravel的路由設(shè)置非常簡(jiǎn)單询一,但是在大型項(xiàng)目中需要配置很多路由信息滤钱,顯得比較臃腫,可以對(duì)路由進(jìn)行如下簡(jiǎn)化:
首先創(chuàng)建一個(gè)中間件 HttpDiscernMiddleware:

<?php

namespace App\Http\Middleware;

use Closure;
use Log;
use App;

class HttpDiscernMiddleware
{
    protected $controller;
    protected $method;
    protected $api_version;

    /**
     * Request Method&Api Version Discern Middleware
     * @param $request
     * @param Closure $next
     * @return mixed
     * @throws \Exception
     */
    public function handle($request, Closure $next)
    {
        $real_method = $request->getRealMethod();
        $scheme_host = $request->getSchemeAndHttpHost();
        $request_uri = $request->getRequestUri();
        $client_ip = $request->getClientIp();
        $content_type = $request->getContentType();
        $base_url = $request->getBaseUrl();

        $data = [
            "real_method"=>$real_method,
            "scheme_host"=>$scheme_host,
            "request_uri"=>$request_uri,
            "client_ip"=>$client_ip,
            "content_type"=>$content_type,
            "base_url"=>$base_url,
        ];

        Log::info("Http Request : ".json_encode($data));

        if (strrpos($request_uri,'?')) {
            $temp = explode('?', $request_uri);
            $temp = explode('/', current($temp));
        }else{
            $temp = explode('/', $request_uri);
        }

        $this->controller = $temp[1];
        $this->method = $temp[2];

        try {
            if (strtolower($this->controller)=="api") {
                $this->api_version = $temp[2];
                $this->controller = $temp[3];
                $this->method = $temp[4];
            }

            $tag = ['@method','@api'];
            $request_method = $this->getProperty(
                'App\Http\Controllers\\'.ucwords($this->controller).'Controller',
                $this->method,
                $tag
            );

            Log::info("request_method: ",$request_method);
            if ($request_method['@method'] != strtolower($real_method)) {
                throw new \Exception('方法不支持');
            }

            if (!empty($request_method['@api'])) {
                if (empty($this->api_version)) {
                    throw new \Exception("@api 版本為空");
                }
                $api = (float) explode(':', $request_method['@api'])[1];
                $req_api = (float) explode('v',$this->api_version)[1];

                if ($api != $req_api) {
                    throw new \Exception("@api 版本不正確");
                }
            }

        } catch (\Exception $e) {
            throw $e;
        }

        return $next($request);
    }

    /**
     * Get Class Property Function
     * @param $class
     * @param $method
     * @param $tags
     * @return array|null
     * @throws \Exception
     */
    public function getProperty($class, $method, $tags)
    {
        try {
            $req_property = null;
            if (empty($tags)) {
                throw new \Exception('Tag 不能空');
            }
            $controller = new \ReflectionClass($class);
            $method = $controller->getMethod($method);
            $doc = $method->getDocComment();
            $matches = array();
            $req_property = array();
            foreach ($tags as $item) {
                preg_match("/".$item."(.*)(\\r\\n|\\r|\\n)/U", $doc, $matches);
                if (isset($matches[1])) {
                    $req_property[$item]  =trim($matches[1]) ;
                }
            }
            if (!isset($req_property['@method'])) {
                throw new \Exception('請(qǐng)?jiān)O(shè)置@method 屬性[必填]');
            }
            return $req_property;

        } catch (\Exception $e) {
            throw $e;
        }
    }
}

HttpDiscernMiddleware的任務(wù)是完成用戶請(qǐng)求和Controller中的方法進(jìn)行匹配拔恰,通過(guò)反射獲取Controller中Function注釋信息(@method,@api)玖绿,這樣可以不需要在routes文件夾下配置很多路由信息了;

在Kernel.php,$routeMiddleware中配置如下:

'discern'=> \App\Http\Middleware\HttpDiscernMiddleware::class,

在RouteServiceProvider 中加入:

    public function boot()
    {
        //

        parent::boot();

        Route::bind('controller', function ($controller) {
            try {
                return app($this->namespace.'\\'.ucwords($controller).'Controller');
            } catch (\Exception $e) {
                throw new \Exception('Controller 解析失敗');
            }
        });
    }

綁定$controller變量為解析后的Controller對(duì)象 ;

然后在routes/web.php中 加入:

Route::group([
    'middleware'=>[
        'discern'
    ]
],function () {
    Route::match(['get','post','put','delete','patch'],'/{controller}/{method}',function ($controller,$method){
        try {
            $result = $controller->$method();
            if(is_scalar($result)){
                return response()->json($result);
            }
            return $result;
        } catch (\Exception $e) {
            throw new Exception($e->getMessage());
        }
    });
});

在routes/api.php中加入:


Route::group([
    'middleware'=>[
        'discern'
    ]
],function () {
    Route::match(['get','post','put','delete','patch'],'/{version}/{controller}/{method}',function ($version,$controller,$method){
        try {
            $result = $controller->$method();
            if(is_scalar($result)){
                return response()->json($result);
            }
            return $result;
        } catch (\Exception $e) {
            throw new Exception($e->getMessage());
        }
    });
});

這樣就配置好web.php 和 api.php了年堆。

這些配置好后就只需要在控制器中配置請(qǐng)求method或者api版本信息 就可以了吞杭,不需要寫繁瑣的路由信息,當(dāng)然可以根據(jù)自己的需要修改变丧。

Demo1: [ 請(qǐng)求uri : http://domain/demo/testGet?user=ethan]

class DemoController extends Controller
{

    /**
     * Controller-Route Demo
     * @method get
     * @return array
     */
    public function testGet()
    {
        $user = $this->getParam("user");
        return view('home')->with($user);
    }
}

@method 定義了請(qǐng)求的方法必須為get

Demo2: [ 請(qǐng)求uri : http://domain/api/v1/demo/testGet?user=ethan]

class DemoController extends Controller
{

    /**
     * Controller-Route Demo
     * @method get
     * @api version:1.0
     * @return array
     */
    public function testGet()
    {
        $user = $this->getParam("user");
        return view('home')->with($user);
    }
}

@method 定義了請(qǐng)求的方法必須為get芽狗,@api 定義了版本為v1(v是version的簡(jiǎn)寫)

其中 @method 支持 [get,post痒蓬,put童擎,delete]

通過(guò)Demo1和Demo2可以通過(guò)注釋來(lái)控制route路由的請(qǐng)求規(guī)則了,達(dá)到了簡(jiǎn)化路由的目的攻晒,并且使用很方便顾复。

?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
  • 序言:七十年代末,一起剝皮案震驚了整個(gè)濱河市鲁捏,隨后出現(xiàn)的幾起案子芯砸,更是在濱河造成了極大的恐慌,老刑警劉巖给梅,帶你破解...
    沈念sama閱讀 211,423評(píng)論 6 491
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件假丧,死亡現(xiàn)場(chǎng)離奇詭異,居然都是意外死亡动羽,警方通過(guò)查閱死者的電腦和手機(jī)包帚,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 90,147評(píng)論 2 385
  • 文/潘曉璐 我一進(jìn)店門,熙熙樓的掌柜王于貴愁眉苦臉地迎上來(lái)运吓,“玉大人婴噩,你說(shuō)我怎么就攤上這事∮鸬拢” “怎么了?”我有些...
    開(kāi)封第一講書人閱讀 157,019評(píng)論 0 348
  • 文/不壞的土叔 我叫張陵迅办,是天一觀的道長(zhǎng)宅静。 經(jīng)常有香客問(wèn)我,道長(zhǎng)站欺,這世上最難降的妖魔是什么姨夹? 我笑而不...
    開(kāi)封第一講書人閱讀 56,443評(píng)論 1 283
  • 正文 為了忘掉前任,我火速辦了婚禮矾策,結(jié)果婚禮上磷账,老公的妹妹穿的比我還像新娘。我一直安慰自己贾虽,他們只是感情好逃糟,可當(dāng)我...
    茶點(diǎn)故事閱讀 65,535評(píng)論 6 385
  • 文/花漫 我一把揭開(kāi)白布。 她就那樣靜靜地躺著,像睡著了一般绰咽。 火紅的嫁衣襯著肌膚如雪菇肃。 梳的紋絲不亂的頭發(fā)上,一...
    開(kāi)封第一講書人閱讀 49,798評(píng)論 1 290
  • 那天取募,我揣著相機(jī)與錄音琐谤,去河邊找鬼。 笑死玩敏,一個(gè)胖子當(dāng)著我的面吹牛斗忌,可吹牛的內(nèi)容都是我干的。 我是一名探鬼主播旺聚,決...
    沈念sama閱讀 38,941評(píng)論 3 407
  • 文/蒼蘭香墨 我猛地睜開(kāi)眼织阳,長(zhǎng)吁一口氣:“原來(lái)是場(chǎng)噩夢(mèng)啊……” “哼!你這毒婦竟也來(lái)了翻屈?” 一聲冷哼從身側(cè)響起陈哑,我...
    開(kāi)封第一講書人閱讀 37,704評(píng)論 0 266
  • 序言:老撾萬(wàn)榮一對(duì)情侶失蹤,失蹤者是張志新(化名)和其女友劉穎伸眶,沒(méi)想到半個(gè)月后惊窖,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體,經(jīng)...
    沈念sama閱讀 44,152評(píng)論 1 303
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡厘贼,尸身上長(zhǎng)有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 36,494評(píng)論 2 327
  • 正文 我和宋清朗相戀三年界酒,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片嘴秸。...
    茶點(diǎn)故事閱讀 38,629評(píng)論 1 340
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡毁欣,死狀恐怖,靈堂內(nèi)的尸體忽然破棺而出岳掐,到底是詐尸還是另有隱情凭疮,我是刑警寧澤,帶...
    沈念sama閱讀 34,295評(píng)論 4 329
  • 正文 年R本政府宣布串述,位于F島的核電站执解,受9級(jí)特大地震影響,放射性物質(zhì)發(fā)生泄漏纲酗。R本人自食惡果不足惜衰腌,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 39,901評(píng)論 3 313
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望觅赊。 院中可真熱鬧右蕊,春花似錦、人聲如沸吮螺。這莊子的主人今日做“春日...
    開(kāi)封第一講書人閱讀 30,742評(píng)論 0 21
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽(yáng)。三九已至坯约,卻和暖如春熊咽,著一層夾襖步出監(jiān)牢的瞬間,已是汗流浹背闹丐。 一陣腳步聲響...
    開(kāi)封第一講書人閱讀 31,978評(píng)論 1 266
  • 我被黑心中介騙來(lái)泰國(guó)打工横殴, 沒(méi)想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留,地道東北人卿拴。 一個(gè)月前我還...
    沈念sama閱讀 46,333評(píng)論 2 360
  • 正文 我出身青樓衫仑,卻偏偏與公主長(zhǎng)得像,于是被迫代替她去往敵國(guó)和親堕花。 傳聞我的和親對(duì)象是個(gè)殘疾皇子文狱,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 43,499評(píng)論 2 348

推薦閱讀更多精彩內(nèi)容