我发现大多数的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
方法来指定当前需要验证的场景名称
默认我们一个控制器对应一个验证器,一个方法对应一个场景名称,基于此特点,我们可以编写一些更为简易的方法来解决验证,我们可以编写一个中间件来解决此问题,点击查看文档说明,中间件完整命名空间为:Itwmw\Validate\Middleware\Laravel\ValidateMiddleware
首先我们需要为他指定控制器和验证器的对应关系,在app/Providers
目录下新建一个ValidateServiceProvider.php
文件,写入如下代码:
<?php namespace App\Providers; use Illuminate\Support\ServiceProvider; use Itwmw\Validate\Middleware\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
方法来接收值即可。
此文章只写了这个扩展的一些基本用法,还有更多的功能,需要大家自己看看文档,来完成自己合适的验证层。
For more laravel technical articles, please visit the laravel tutorial column!
The above is the detailed content of Analyze how to carry out Laravel form verification layered design and verification scenario application. For more information, please follow other related articles on the PHP Chinese website!