文件:中间件
中間件概念: 中間件在請求和回應的生命週期中執行操作,用於處理請求或修改回應。(可以回頭複習第 2 天:Laravel 啟服務與請求的生命週期)
建立中間件: 使用Artisan
指令建立中間件並定義處理邏輯。
註冊中間件: 在Kernel
檔案中註冊中間件以便在路由中使用。
使用中間件: 可以在路由或控制器中套用中間件來執行請求過濾。
中間件是 Laravel 中用於處理 HTTP 請求的機制,當請求到達應用程式之前或在回應傳送到使用者之前執行一些操作,通常用於認證、授權、日誌記錄、請求修改等。
中間件可以理解為一個處理 HTTP 請求的過濾器。
當一個請求進入應用程序時,Laravel 的 HTTP 核心會依序將該請求通過路由、控制器(如果有的話)、以及註冊的 middleware。
每個中間件通常包含一個 handle 方法,該方法接收請求並可選擇處理或轉送請求。
創建中間件
指令 php artisan make:middleware CheckAge
,然後在 app/Http/Middleware/CheckAge.php
定義中間件的邏輯。
namespace App\Http\Middleware;
use Closure;
use Illuminate\Http\Request;
use Symfony\Component\HttpFoundation\Response;
class CheckAge
{
/**
* Handle an incoming request.
*
* @param \Illuminate\Http\Request $request
* @param \Closure $next
* @return \Symfony\Component\HttpFoundation\Response
*/
public function handle(Request $request, Closure $next)
{
// 檢查用戶是否年滿 18 歲
if ($request->age < 18) {
return response('You are not old enough.', 403);
}
return $next($request);
}
}
$next($request)
的作用
在 middleware 中,$next($request)
的作用是將控制權交給下一個 middleware 或路由處理器(controller)。
也就是當調用 $next($request)
時,控制流程將會繼續向下,直到達到最後一個 middleware 或是路由的處理器。
註冊自定義中間件
中間件需要在 app/Http/Kernel.php
檔案中註冊,以便可以在路由中使用它。
protected $routeMiddleware = [
// 其他中間件
'checkage' => \App\Http\Middleware\CheckAge::class,
];
// routes/web.php
Route::get('/profile', function () {
// 僅當 age 大於等於 18 時才能存取此路由
})->middleware('checkage');
// app/Http/Controllers/ProfileController.php
namespace App\Http\Controllers;
use Illuminate\Http\Request;
class ProfileController extends Controller
{
public function __construct()
{
$this->middleware('checkage');
}
public function show()
{
// 僅當 age 大於等於 18 時才能存取此方法
}
}
使用者訪問特定路由,要先確認是否已經登入,有登入的話轉跳歡迎頁面,沒有登入的話就轉跳到登入頁請他重新登入,所以現在需要建立一個中間件來檢查使用者是否已登入。
step 1 - 建立新的中間件
指令 php artisan make:middleware CheckAuthenticated
。
step 2 - 在中間件上寫邏輯判斷
指令新建的中間件檔案 app/Http/Middleware/CheckAuthenticated.php
新增檢查使用者是否已登入的邏輯。
namespace App\Http\Middleware;
use Closure;
use Illuminate\Http\Request;
use Symfony\Component\HttpFoundation\Response;
class CheckAuthenticated
{
/**
* Handle an incoming request.
*
* @param \Illuminate\Http\Request $request
* @param \Closure $next
* @return \Symfony\Component\HttpFoundation\Response
*/
public function handle(Request $request, Closure $next)
{
// 檢查用戶是否登入
if (!auth()->check()) {
// 如果使用者未登錄,重定向到登錄頁面
return redirect()->route('login');
}
// 繼續處理請求
return $next($request);
}
}
step 3 - 註冊中間件
在 app/Http/Kernel.php
檔案中註冊中間件。
把建立的中間件加到 $routeMiddleware
陣列中,就可以在路由中使用它。
protected $routeMiddleware = [
// 其他中間件
'authcheck' => \App\Http\Middleware\CheckAuthenticated::class,
];
step 4 - 使用中間件
有兩種方法可以使用中間件,一種是直接掛在路由上;另一種寫在控制器,當路由引用靜態呼叫控制器方法的時候,中間件也會被使用到。
routes/web.php
檔案中,使用剛建立的中間件來保護某些路由
use Illuminate\Support\Facades\Route;
Route::get('/dashboard', function () {
return 'This is the dashboard page!';
})->middleware('authcheck'); // 使用中間件保護此路由
Route::get('/login', function () {
return 'This is the login page!';
})->name('login'); // 設定登入路由的名稱
// app/Http/Controllers/DashboardController.php
namespace App\Http\Controllers;
use Illuminate\Http\Request;
class DashboardController extends Controller
{
public function __construct()
{
// 將中間件應用於所有方法
$this->middleware('authcheck');
}
public function index()
{
return 'Welcome to the dashboard!';
}
}
// routes/web.php
use App\Http\Controllers\DashboardController;
Route::get('/dashboard', [DashboardController::class, 'index']);
step 5 - 測試
test_case1 存取受保護的路由:嘗試存取 /dashboard
頁面,未登入的使用者應被重新導向至 /login
頁面。
test_case2 登入使用者測試:登入後造訪 /dashboard
,應能看到「Welcome to the dashboard!」訊息。