解析如何進(jìn)行Laravel表單驗(yàn)證分層設(shè)計(jì)和驗(yàn)證場(chǎng)景應(yīng)用

? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ?

思考

我發(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教程欄目!

? 版權(quán)聲明
THE END
喜歡就支持一下吧
點(diǎn)贊12 分享
站長(zhǎng)的頭像-小浪學(xué)習(xí)網(wǎng)月度會(huì)員