思考
我發(fā)現(xiàn)大多數(shù)的laravel用戶會(huì)將驗(yàn)證規(guī)則寫(xiě)在controller下,但這會(huì)有一個(gè)問(wèn)題,使代碼雜亂且無(wú)法復(fù)用相同的規(guī)則。在crud為主的項(xiàng)目中,我們會(huì)發(fā)現(xiàn)好多字段以及它們的驗(yàn)證規(guī)則是相同的,我們一般會(huì)化身為cv工程師,再?gòu)?fù)制一份,那么為什么不加一層驗(yàn)證層?
伴隨這個(gè)問(wèn)題,然后去看了別的開(kāi)源項(xiàng)目的代碼,發(fā)現(xiàn)TP用戶的驗(yàn)證會(huì)放在一個(gè)單獨(dú)的類(lèi)中,并且有驗(yàn)證場(chǎng)景來(lái)支持他們復(fù)用規(guī)則,于是我尋找laravel中有沒(méi)有對(duì)應(yīng)的解決方案,然后發(fā)現(xiàn)了微擎的一個(gè)驗(yàn)證器w7/engine-validate,接下里的文章就依賴此擴(kuò)展來(lái)講如何增加一個(gè)驗(yàn)證層
安裝
composer require w7/engine-validate
介紹
首先此驗(yàn)證器也是基于illuminate/validation的,關(guān)于它的詳細(xì)說(shuō)明可以直接查看它的文檔,這里就不過(guò)多說(shuō)明了。
使用
首先我們建立一個(gè)和控制器相對(duì)應(yīng)的驗(yàn)證層
app ├── Http │ ├── Controllers │ │ └── UserController.php │ └── Validate │ └── UserValidate.php
驗(yàn)證器
驗(yàn)證器代碼:
class UserValidate extends Validate{ protected $rule = [ 'user' => 'required|email', 'pass' => 'required|alpha_num' ]; protected $message = [ 'user.required' => '賬號(hào)不可為空', 'pass.required' => '密碼不可為空', ]; protected $customAttributes = [ 'user' => '賬號(hào)', 'pass' => '密碼', ];}
控制器代碼:
class UserController extends BaseController{ use AuthorizesRequests, DispatchesJobs, ValidatesRequests; public function login(Request $request) { $data = UserValidate::make()->check($request->all()); }}
這個(gè)時(shí)候,如果值不符合要求,會(huì)拋出一個(gè)ValidateException異常,我們可以選擇手動(dòng)捕獲,也可以選擇在異常捕獲類(lèi)里面做一個(gè)全局的處理:
public function render($request, Throwable $e) { if ($e instanceof ValidateException) { return response()->json([ 'code' => -1, 'message' => $e->getMessage() ]); } return parent::render($request, $e); }
這樣我們就不需要再控制器里面管理任何的驗(yàn)證異常了。
此時(shí),控制器中的$data一定是符合我們需求的數(shù)據(jù),然后可以緊接著做對(duì)應(yīng)的業(yè)務(wù)處理
驗(yàn)證場(chǎng)景
這個(gè)時(shí)候,如果我們的UserController控制器中又添加了一個(gè)register方法,在以上兩個(gè)字段的需求同時(shí)增加了name,應(yīng)該如何處理呢?
我們可以使用類(lèi)的$scene屬性來(lái)指定某一場(chǎng)景下需要驗(yàn)證的字段
驗(yàn)證器代碼修改如下:
class UserValidate extends Validate{ protected $rule = [ 'user' => 'required|email', 'pass' => 'required|alpha_num', 'name' => 'required|alpha' ]; protected $message = [ 'user.required' => '賬號(hào)不可為空', 'pass.required' => '密碼不可為空', ]; protected $customAttributes = [ 'user' => '賬號(hào)', 'pass' => '密碼', 'name' => '用戶名稱', ]; protected $scene = [ 'login' => ['user', 'pass'], 'register' => ['user', 'pass', 'name'] ];}
此時(shí):login場(chǎng)景對(duì)應(yīng)的驗(yàn)證user和pass字段,而register場(chǎng)景對(duì)應(yīng)的驗(yàn)證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()); }}
使用驗(yàn)證器的scene方法來(lái)指定當(dāng)前需要驗(yàn)證的場(chǎng)景名稱
驗(yàn)證中間件
默認(rèn)我們一個(gè)控制器對(duì)應(yīng)一個(gè)驗(yàn)證器,一個(gè)方法對(duì)應(yīng)一個(gè)場(chǎng)景名稱,基于此特點(diǎn),我們可以編寫(xiě)一些更為簡(jiǎn)易的方法來(lái)解決驗(yàn)證,我們可以編寫(xiě)一個(gè)中間件來(lái)解決此問(wèn)題,點(diǎn)擊查看文檔說(shuō)明,中間件完整命名空間為:ItwmwValidateMiddlewareLaravelValidateMiddleware
中間件設(shè)置
首先我們需要為他指定控制器和驗(yàn)證器的對(duì)應(yīng)關(guān)系,在app/Providers目錄下新建一個(gè)ValidateServiceProvider.php文件,寫(xiě)入如下代碼:
<?php namespace AppProviders; use IlluminateSupportServiceProvider; use ItwmwValidateMiddlewareValidateMiddlewareConfig; class ValidateServiceProvider extends ServiceProvider{ public function register() { ValidateMiddlewareConfig::instance() ->setAutoValidatePath('AppHttpControllers', 'AppHttpValidate'); }}
其中setAutoValidatePath為指定控制器和驗(yàn)證器的對(duì)應(yīng)關(guān)系,可以設(shè)定多個(gè),不限制數(shù)量,然后我們將ValidateServiceProvider注冊(cè)一下,在config/app.php文件中找到providers,在其中添加AppProvidersValidateServiceProvider::class
注意:不可以放在IlluminateValidationValidationServiceProvider::class之前
使用中間件
這個(gè)時(shí)候,我們可以將中間件注冊(cè)為全局中間件,也可以不注冊(cè),注冊(cè)方法:中間件《Laravel 7 中文文檔》
定義路由:
Route::middleware(ValidateMiddleware::class)->group(function () { Route::any('/login', [AppHttpControllersUserController::class, 'login']); Route::any('/register', [AppHttpControllersUserController::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); }}
這個(gè)時(shí)候,我們就不需要手動(dòng)指定驗(yàn)證器已經(jīng)場(chǎng)景名了,中間件會(huì)自動(dòng)處理對(duì)應(yīng)的驗(yàn)證規(guī)則,我們只需要使用get_validate_data方法來(lái)接收值即可。
結(jié)尾
此文章只寫(xiě)了這個(gè)擴(kuò)展的一些基本用法,還有更多的功能,需要大家自己看看文檔,來(lái)完成自己合適的驗(yàn)證層。
更多l(xiāng)aravel技術(shù)文章,請(qǐng)?jiān)L問(wèn)laravel教程欄目!