laravel 基礎(chǔ)教程 —— 中間件

中間件

簡(jiǎn)介

HTTP 中間件為你的應(yīng)用提供了一種便利的機(jī)制去過濾客戶端的請(qǐng)求,比如說laravel中自帶的用來(lái)驗(yàn)證用戶是否已經(jīng)認(rèn)證的中間件宴杀,如果用戶的認(rèn)證沒有通過癣朗,那么他將被重定向到登錄視圖拾因。而如果用戶已經(jīng)通過認(rèn)證,那么他的請(qǐng)求就會(huì)被認(rèn)證中間件通過旷余,并將請(qǐng)求傳遞給應(yīng)用绢记。

中間件可以處理多種任務(wù),不僅僅只是用于驗(yàn)證用戶認(rèn)證正卧。比如你可以創(chuàng)建一個(gè)跨同源策略的中間件蠢熄,用來(lái)處理每個(gè)請(qǐng)求在被響應(yīng)前添加正確的響應(yīng)頭,你還可以創(chuàng)造一個(gè)日志中間件炉旷,在應(yīng)用被請(qǐng)求時(shí)優(yōu)先記錄下請(qǐng)求信息签孔。

Laravel框架本身提供了一些中間件叉讥,它們包括維護(hù)、認(rèn)證饥追、csrf保護(hù)图仓、session等中間件,這些中間件都被定義在app\Http\Middleware目錄中但绕。

定義中間件

為了創(chuàng)建一個(gè)新的中間件救崔,你可以直接使用laravel提供的 make:middleware artisan命令:

php artisan make:middleware AgeMiddleware

這條命令會(huì)在app\Http\Middleware目錄下創(chuàng)建一個(gè)AgeMiddleware.php文件。我們創(chuàng)造這么一個(gè)中間件捏顺,讓只有年齡大于200的路由通過:

<?php

namespace App\Http\Middleware;

use Closure;

class AgeMiddleware {
  public function handle ($request, Closure $next) {
    if ($request->get('age') > 200) {
      return $next($request);
    }
    return redirect('home'); 
  }
}

你可以看到六孵,如果請(qǐng)求中所提供的年齡小于等于200,請(qǐng)求將被直接返回一個(gè)重定向信息到客戶端,而如果年齡大于200幅骄,請(qǐng)求將被中間件繼續(xù)傳遞給應(yīng)用劫窒。為了在中間件中將請(qǐng)求轉(zhuǎn)交給應(yīng)用,你可以使用$next回調(diào)函數(shù)拆座,并將$request傳遞進(jìn)去烛亦。

你可以建立一系列的中間件來(lái)過濾客戶端的請(qǐng)求,這樣每一層中間件都可以檢查請(qǐng)求懂拾,如果通過煤禽,則將請(qǐng)求轉(zhuǎn)交到下一層,如果不通過則直接被駁回岖赋。

前行/后行 中間件

其實(shí)檬果,在中間件中不僅僅可以定義前行中間件,即在請(qǐng)求被轉(zhuǎn)交到應(yīng)用之前進(jìn)行處理的中間件唐断。

<?php 

namespace App\Http\Middleware;

use Closure;

class BeforeMiddleware {
  public function handle ($request, Closure $next) {
    // Perform action

    return $next($request);
  }
}

也可以定義優(yōu)先轉(zhuǎn)交請(qǐng)求給應(yīng)用的后執(zhí)行中間件选脊。

<? php

namespace App\Http\Middleware;

use Closure;

class AfterMiddleware {
  public function handle ($request, Closure $next) {
    $response = $next($request);
    // Perform action
    return $response;
  }
}

注冊(cè)中間件

全局中間件

如果你需要一個(gè)可以過濾所有請(qǐng)求的中間件,那么你可以注冊(cè)一個(gè)全局中間件脸甘。你需要先定義好中間件恳啥,然后在app/Http/kernel.php中的$middleware數(shù)組屬性中進(jìn)行追加注冊(cè)。

分配中間件到路由

如果你想要分配中間件到特定的路由丹诀,那么你需要在app/Http/kernel.php文件中$routeMiddleware屬性中進(jìn)行追加注冊(cè)钝的,在這里你應(yīng)該定義一個(gè)短字符的別名,以便于你在路由分配時(shí)快速指定铆遭。

// Within App\Http\Kernel Class...

protected $routeMiddleware = [
  'auth' => \App\Http\Middleware\Authenticate::class,
  'auth.basic' => \App\Http\Middleware\AuthenticateBasicAuth::class,
  'gust' => \App\Http\Middleware\RedirectIfAuthenticated::class,
  'throttle' => \App\Http\Middleware\ThrottleRequest::class,
];

一旦你的中間件被注冊(cè)在了kernel文件中硝桩,那么你就可以在定義路由時(shí)使用middleware選項(xiàng)進(jìn)行中間件分配:

Route::get('admin/profile', ['middleware' => 'auth', function () {
  // 
}]);

你可以通過這么做來(lái)分配多個(gè)中間件:

Route::get('/', ['middleware' => ['first', 'second'], function () {
  // 
}]);

當(dāng)然laravel也允許你通過鏈?zhǔn)椒椒?code>middleware去進(jìn)行中間件分配:

Route::get('/', function () {
 // 
})->middleware(['first', 'second']);

事實(shí)上,你也可以使用完全類名來(lái)進(jìn)行中間件分配:

use App\Http\Middleware\FooMiddleware;

Route::get('admin/profile', ['middleware' => FooMiddleware::class, function () {
  // 
}]);

中間件組

有時(shí)候你可能希望在分配路由時(shí)枚荣,可以通過一個(gè)別名來(lái)分配一系列的中間件到路由碗脊。你可以在kernel文件中使用$middlewareGroups屬性來(lái)進(jìn)行注冊(cè).

laravel自帶了webapi中間件組:

protected $middlewareGroups = [
  'web' => [
        \App\Http\Middleware\EncryptCookies::class,
        \Illuminate\Cookie\Middleware\AddQueuedCookiesToResponse::class,
        \Illuminate\Session\Middleware\StartSession::class,
        \Illuminate\View\Middleware\ShareErrorsFromSession::class,
        \App\Http\Middleware\VerifyCsrfToken::class,
    ],

    'api' => [
        'throttle:60,1',
        'auth:api',
    ],
];

一旦注冊(cè)了中間件組,你可以使用相同語(yǔ)法去分配中間件組到路由:

Route::get('/', ['middleware' => ['web'], function () {
  // 
}]);

事實(shí)上橄妆,laravel自帶的web中間件組已經(jīng)被默認(rèn)啟用衙伶,所有在routes.php中被定義的路由都被分配了此中間件祈坠。你可以在RouteServiceProvider.php文件中進(jìn)行修改.

帶參數(shù)的中間件

中間件也可以接收額外的自定義參數(shù)。比如說你可能需要一個(gè)中間件來(lái)驗(yàn)證已認(rèn)證的用戶的權(quán)限問題矢劲。你可能需要傳遞一個(gè)角色名稱參數(shù)來(lái)執(zhí)行相應(yīng)的行為.那么你需要?jiǎng)?chuàng)建一個(gè)RoleMiddleware來(lái)接收一個(gè)角色名稱作為額外的參數(shù).
額外的參數(shù)將會(huì)被傳遞在$next參數(shù)之后:

<?php

namesapce App\Http\Middleware;

use Closure;

class RoleMiddleware {
  public function handle ($request, Closure $next, $role) {
    if (!$request->user()->hasRole($role)) {
      // Redirect...
    }

    return $next($request);
  }
}

帶參數(shù)的中間件在分配給路由時(shí)需要在中間件別名之后跟:來(lái)分割別名和參數(shù)颁虐,多個(gè)參數(shù)需要使用,分隔:

Route::post('post/{id}', ['middleware' => 'role:editor', function ($id) {
  // 
}]);

末端中間件

有時(shí)候你可能需要在響應(yīng)被發(fā)送到客戶端之后繼續(xù)處理一些任務(wù),比如說 session中間件在laravel中就是響應(yīng)被發(fā)送出去之后才將session信息進(jìn)行存儲(chǔ)操作卧须。這時(shí)候你可以通過在中間件中添加terminate方法來(lái)定義一個(gè)末端中間件:

<?php

namespace Illuminate\Session\Middleware;

use Closure;

class StartSession {
  public function hanlde ($request, Closure $next) {
    return $next($request);
  }

  public function terminate($request, $response) {
    // Store the sessin data...
  }
}

terminate方法會(huì)接收請(qǐng)求和響應(yīng)另绩,一旦你定義了一個(gè)末端中間件,你應(yīng)該在kernel文件中將其添加到全局中間件中.

每當(dāng)中間件中的terminate方法被調(diào)用花嘶,laravel都會(huì)從服務(wù)容器中返回一個(gè)新的中間件實(shí)例笋籽,如果你想使用同一個(gè)實(shí)例,你應(yīng)該將其注冊(cè)在服務(wù)容器中并使用singleton方法注冊(cè).

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
  • 序言:七十年代末椭员,一起剝皮案震驚了整個(gè)濱河市车海,隨后出現(xiàn)的幾起案子,更是在濱河造成了極大的恐慌隘击,老刑警劉巖侍芝,帶你破解...
    沈念sama閱讀 221,820評(píng)論 6 515
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件,死亡現(xiàn)場(chǎng)離奇詭異埋同,居然都是意外死亡州叠,警方通過查閱死者的電腦和手機(jī),發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 94,648評(píng)論 3 399
  • 文/潘曉璐 我一進(jìn)店門凶赁,熙熙樓的掌柜王于貴愁眉苦臉地迎上來(lái)咧栗,“玉大人,你說我怎么就攤上這事虱肄≈掳澹” “怎么了?”我有些...
    開封第一講書人閱讀 168,324評(píng)論 0 360
  • 文/不壞的土叔 我叫張陵咏窿,是天一觀的道長(zhǎng)斟或。 經(jīng)常有香客問我,道長(zhǎng)集嵌,這世上最難降的妖魔是什么萝挤? 我笑而不...
    開封第一講書人閱讀 59,714評(píng)論 1 297
  • 正文 為了忘掉前任,我火速辦了婚禮纸淮,結(jié)果婚禮上平斩,老公的妹妹穿的比我還像新娘亚享。我一直安慰自己咽块,他們只是感情好,可當(dāng)我...
    茶點(diǎn)故事閱讀 68,724評(píng)論 6 397
  • 文/花漫 我一把揭開白布欺税。 她就那樣靜靜地躺著侈沪,像睡著了一般揭璃。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發(fā)上亭罪,一...
    開封第一講書人閱讀 52,328評(píng)論 1 310
  • 那天瘦馍,我揣著相機(jī)與錄音,去河邊找鬼应役。 笑死情组,一個(gè)胖子當(dāng)著我的面吹牛,可吹牛的內(nèi)容都是我干的箩祥。 我是一名探鬼主播院崇,決...
    沈念sama閱讀 40,897評(píng)論 3 421
  • 文/蒼蘭香墨 我猛地睜開眼,長(zhǎng)吁一口氣:“原來(lái)是場(chǎng)噩夢(mèng)啊……” “哼袍祖!你這毒婦竟也來(lái)了底瓣?” 一聲冷哼從身側(cè)響起,我...
    開封第一講書人閱讀 39,804評(píng)論 0 276
  • 序言:老撾萬(wàn)榮一對(duì)情侶失蹤蕉陋,失蹤者是張志新(化名)和其女友劉穎捐凭,沒想到半個(gè)月后,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體凳鬓,經(jīng)...
    沈念sama閱讀 46,345評(píng)論 1 318
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡茁肠,尸身上長(zhǎng)有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 38,431評(píng)論 3 340
  • 正文 我和宋清朗相戀三年,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了缩举。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片官套。...
    茶點(diǎn)故事閱讀 40,561評(píng)論 1 352
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡,死狀恐怖蚁孔,靈堂內(nèi)的尸體忽然破棺而出奶赔,到底是詐尸還是另有隱情,我是刑警寧澤杠氢,帶...
    沈念sama閱讀 36,238評(píng)論 5 350
  • 正文 年R本政府宣布站刑,位于F島的核電站,受9級(jí)特大地震影響鼻百,放射性物質(zhì)發(fā)生泄漏绞旅。R本人自食惡果不足惜,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 41,928評(píng)論 3 334
  • 文/蒙蒙 一温艇、第九天 我趴在偏房一處隱蔽的房頂上張望因悲。 院中可真熱鬧,春花似錦勺爱、人聲如沸晃琳。這莊子的主人今日做“春日...
    開封第一講書人閱讀 32,417評(píng)論 0 24
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽(yáng)卫旱。三九已至人灼,卻和暖如春,著一層夾襖步出監(jiān)牢的瞬間顾翼,已是汗流浹背投放。 一陣腳步聲響...
    開封第一講書人閱讀 33,528評(píng)論 1 272
  • 我被黑心中介騙來(lái)泰國(guó)打工, 沒想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留适贸,地道東北人灸芳。 一個(gè)月前我還...
    沈念sama閱讀 48,983評(píng)論 3 376
  • 正文 我出身青樓,卻偏偏與公主長(zhǎng)得像拜姿,于是被迫代替她去往敵國(guó)和親耗绿。 傳聞我的和親對(duì)象是個(gè)殘疾皇子,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 45,573評(píng)論 2 359

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

  • 路由 路由(routing)就是通過互聯(lián)的網(wǎng)絡(luò)把信息從源地址傳輸?shù)侥康牡刂返幕顒?dòng)砾隅。路由發(fā)生在OSI網(wǎng)絡(luò)參考模型中的...
    Dearmadman閱讀 2,860評(píng)論 2 9
  • 簡(jiǎn)介 laravel 使實(shí)施認(rèn)證的變得非常簡(jiǎn)單误阻,事實(shí)上,它提供了非常全面的配置項(xiàng)以適應(yīng)應(yīng)用的業(yè)務(wù)晴埂。認(rèn)證的配置文件存...
    Dearmadman閱讀 6,140評(píng)論 2 13
  • Spring Cloud為開發(fā)人員提供了快速構(gòu)建分布式系統(tǒng)中一些常見模式的工具(例如配置管理亭珍,服務(wù)發(fā)現(xiàn)鸣剪,斷路器,智...
    卡卡羅2017閱讀 134,702評(píng)論 18 139
  • 0.1配置1.模板繼承2.控制器3.git4.支付寶支付的流程5.路由6.中間件7.請(qǐng)求8.laravel 學(xué)習(xí)筆...
    云龍789閱讀 808評(píng)論 0 5
  • github地址誊辉,歡迎大家提交更新。 express() express()用來(lái)創(chuàng)建一個(gè)Express的程序恼蓬。ex...
    Programmer客棧閱讀 2,533評(píng)論 0 1