我發現大多數的Laravel使用者會將驗證規則寫在Controller下,但這會有一個問題,使程式碼雜亂且無法複用相同的規則。在CRUD為主的專案中,我們會發現好多欄位以及它們的驗證規則是相同的,我們一般會化身為CV工程師,再複製一份,那麼為什麼不加一層驗證層?
伴隨這個問題,然後去看了別的開源專案的程式碼,發現TP使用者的驗證會放在一個單獨的類中,並且有驗證場景
來支援他們複用規則,於是我尋找Laravel
中有沒有對應的解決方案,然後發現了微擎的一個驗證器w7/engine-validate
,接下里的文章就依賴此擴充套件來講如何增加一個驗證層
composer require w7/engine-validate
首先此驗證器也是基於illuminate/validation
的,關於它的詳細說明可以直接檢視它的文件,這裡就不過多說明了。
首先我們建立一個和控制器相對應的驗證層
app
├── Http
│ ├── Controllers
│ │ └── UserController.php
│ └── Validate
│ └── UserValidate.php
驗證器
驗證器程式碼:
class UserValidate extends Validate
{
protected $rule = [
'user' => 'required|email',
'pass' => 'required|alpha_num'
];
protected $message = [
'user.required' => '賬號不可為空',
'pass.required' => '密碼不可為空',
];
protected $customAttributes = [
'user' => '賬號',
'pass' => '密碼',
];
}
控制器程式碼:
class UserController extends BaseController
{
use AuthorizesRequests, DispatchesJobs, ValidatesRequests;
public function login(Request $request)
{
$data = UserValidate::make()->check($request->all());
}
}
這個時候,如果值不符合要求,會丟擲一個ValidateException
異常,我們可以選擇手動捕獲,也可以選擇在異常捕獲類裡面做一個全域性的處理:
public function render($request, Throwable $e)
{
if ($e instanceof ValidateException) {
return response()->json([
'code' => -1,
'message' => $e->getMessage()
]);
}
return parent::render($request, $e);
}
這樣我們就不需要再控制器裡面管理任何的驗證異常了。
此時,控制器中的$data
一定是符合我們需求的資料,然後可以緊接著做對應的業務處理
驗證場景
這個時候,如果我們的UserController
控制器中又新增了一個register
方法,在以上兩個欄位的需求同時增加了name
,應該如何處理呢?
我們可以使用類的$scene
屬性來指定某一場景下需要驗證的欄位
驗證器程式碼修改如下:
class UserValidate extends Validate
{
protected $rule = [
'user' => 'required|email',
'pass' => 'required|alpha_num',
'name' => 'required|alpha'
];
protected $message = [
'user.required' => '賬號不可為空',
'pass.required' => '密碼不可為空',
];
protected $customAttributes = [
'user' => '賬號',
'pass' => '密碼',
'name' => '使用者名稱稱',
];
protected $scene = [
'login' => ['user', 'pass'],
'register' => ['user', 'pass', 'name']
];
}
此時:login
場景對應的驗證user
和pass
欄位,而register
場景對應的驗證user
,pass
,name
欄位
控制器程式碼修改如下:
class UserController extends BaseController
{
use AuthorizesRequests, DispatchesJobs, ValidatesRequests;
public function login(Request $request)
{
$data = UserValidate::make()->scene('login')->check($request->all());
}
public function register(Request $request)
{
$data = UserValidate::make()->scene('register')->check($request->all());
}
}
使用驗證器的scene
方法來指定當前需要驗證的場景名稱
驗證中介軟體
預設我們一個控制器對應一個驗證器,一個方法對應一個場景名稱,基於此特點,我們可以編寫一些更為簡易的方法來解決驗證,當然此擴充套件也提供了一種解決方案,點選檢視文件說明,擴充套件提供了一箇中介軟體來完成此需求,中介軟體完整名稱空間為:W7\Validate\Support\Middleware\Laravel\ValidateMiddleware
中介軟體設定
首先我們需要為他指定控制器和驗證器的對應關係,在app/Providers
目錄下新建一個ValidateServiceProvider.php
檔案,寫入如下程式碼:
<?php
namespace App\Providers;
use Illuminate\Support\ServiceProvider;
use W7\Validate\Support\Storage\ValidateMiddlewareConfig;
class ValidateServiceProvider extends ServiceProvider
{
public function register()
{
ValidateMiddlewareConfig::instance()
->setAutoValidatePath('App\\Http\\Controllers\\', 'App\\Http\\Validate\\');
}
}
其中setAutoValidatePath
為指定控制器和驗證器的對應關係,可以設定多個,不限制數量,然後我們將ValidateServiceProvider
註冊一下,在config/app.php
檔案中找到providers
,在其中新增App\Providers\ValidateServiceProvider::class
注意:不可以放在
Illuminate\Validation\ValidationServiceProvider::class
之前
使用中介軟體
這個時候,我們可以將中介軟體註冊為全域性中介軟體,也可以不註冊,註冊方法:中介軟體《Laravel 7 中文文件》
定義路由:
Route::middleware(ValidateMiddleware::class)->group(function () {
Route::any('/login', [\App\Http\Controllers\UserController::class, 'login']);
Route::any('/register', [\App\Http\Controllers\UserController::class, 'register']);
});
控制器程式碼修改如下:
class UserController extends BaseController
{
use AuthorizesRequests, DispatchesJobs, ValidatesRequests;
public function login(Request $request)
{
$data = get_validate_data($request);
}
public function register(Request $request)
{
$data = get_validate_data($request);
}
}
這個時候,我們就不需要手動指定驗證器已經場景名了,中介軟體會自動處理對應的驗證規則,我們只需要使用get_validate_data
方法來接收值即可。
此文章只寫了這個擴充套件的一些基本用法,還有更多的功能,需要大家自己看看文件,來完成自己合適的驗證層。
本作品採用《CC 協議》,轉載必須註明作者和本文連結