首頁
編程語言
C語言|JAVA編程
Python編程
網頁編程
ASP編程|PHP編程
JSP編程
數據庫
MYSQL數據庫|SqlServer數據庫
Oracle數據庫|DB2數據庫
您现在的位置: 程式碼之家 >> 編程語言 >  >> 網頁程式設計 >> PHP 程式設計 >> PHP 綜合知識

Laravel FormRequest 表單驗證深度解析:異常處理流程與自定義錯誤響應實現

     編輯:PHP 綜合知識

FormRequest 核心價值

將驗證邏輯從 Controller 剝離,實現:

  • 單一職責:Controller 專注業務,驗證邏輯復用
  • 授權控制:authorize() 方法整合權限判斷
  • 自動觸發:類型提示注入自動驗證,失敗自動響應

基本使用流程

php artisan make:request StoreCommentRequest
namespace App\Http\Requests;

class StoreCommentRequest extends Request {
    public function authorize() {
        return true;  // 或加入權限邏輯:return $this->user()->can('comment');
    }
    
    public function rules() {
        return [
            'comment' => 'required|string|max:1000',
            'rating' => 'required|integer|between:1,5',
        ];
    }
    
    // 可選:自定義錯誤信息
    public function messages() {
        return [
            'comment.required' => '評論內容不能為空',
            'rating.between' => '評分必須在 1-5 之間',
        ];
    }
}
// Controller
public function store(StoreCommentRequest $request) {
    // 驗證已通過,$request->validated() 獲取安全數據
    $comment = Comment::create($request->validated());
    return response()->json($comment, 201);
}

異常處理流程源碼追蹤

  1. 服務提供者註冊:ValidationServiceProvider::registerValidationResolverHook() 監聽容器解析 ValidatesWhenResolved 接口實例
  2. 自動驗證觸發:容器解析 FormRequest 後調用 validate() (來自 ValidatesWhenResolvedTrait)
  3. 驗證失敗拋出異常:FormRequest::failedValidation() 拋出 HttpResponseException,攜帶構建好的 Response
  4. 路由層捕獲處理:Route::run() 捕獲 HttpResponseException 直接返回 $e->getResponse(),**繞過全局異常處理器**

響應構建邏輯

// FormRequest::response() 簡化版
if ($this->ajax() || $this->wantsJson()) {
    return new JsonResponse($errors, 422);  // API 請求
}
return $this->redirector->to($this->getRedirectUrl())
    ->withInput($this->except($this->dontFlash))
    ->withErrors($errors, $this->errorBag);  // 表單請求

自定義錯誤處理方案

方案一:重寫 failedValidation 拋出自定義異常 (推薦)

// app/Http/Requests/Request.php (基類)
namespace App\Http\Requests;

use Illuminate\Foundation\Http\FormRequest;
use Illuminate\Http\Exceptions\HttpResponseException;
use App\Exceptions\ValidationException;  // 自定義異常

abstract class Request extends FormRequest {
    protected function failedValidation(\Illuminate\Contracts\Validation\Validator $validator) {
        throw new ValidationException($validator);  // 攜帶 Validator 實例
    }
}

// app/Exceptions/ValidationException.php
namespace App\Exceptions;

use Illuminate\Validation\Validator;
use Illuminate\Http\Exceptions\HttpResponseException;

class ValidationException extends HttpResponseException {
    public function __construct(Validator $validator) {
        $response = request()->ajax() || request()->wantsJson()
            ? response()->json(['errors' => $validator->errors()], 422)
            : redirect()->back()->withErrors($validator)->withInput();
        parent::__construct($response);
    }
}

方案二:在 Handler 中處理 (不推薦,因 HttpResponseException 被路由層截獲)

需在 Route::run() 之前處理,可通過中間件或重寫路由調度實現,複雜度高。

方案三:全局 API 響應格式統一 (最實用)

// app/Exceptions/Handler.php
public function render($request, Exception $e) {
    if ($e instanceof \Illuminate\Validation\ValidationException) {
        return response()->json([
            'success' => false,
            'message' => '驗證失敗',
            'errors' => $e->errors(),
        ], 422);
    }
    return parent::render($request, $e);
}

⚠️ 注意:FormRequest 拋出的是 HttpResponseException 而非 ValidationException,需在基類中轉換或使用中間件攔截。

進階技巧

總結

FormRequest 是 Laravel 表單驗證的最佳實踐。理解其異常處理流程(Validator → HttpResponseException → Route 捕獲)是實現自定義錯誤響應的關鍵。推薦在基類 App\Http\Requests\Request 中重寫 failedValidation() 拋出自定義異常,或在 Handler 中統一 API 錯誤格式,避免在每個 Controller 中重複處理。

  1. 上一篇文章:
  2. 下一篇文章:
Copyright © 程式碼之家 All Rights Reserved
需求實現
條件驗證'email' => 'required_if:account_type,email'
數組字段驗證'items.*.name' => 'required|string'
驗證後修改數據重寫 validated() 或使用 prepareForValidation()
文件上傳驗證'avatar' => 'required|image|mimes:jpg,png|max:2048'
唯一性驗證 (排除自己)'email' => 'unique:users,email,' . $this->user()->id