Laravel 自定义表单请求验证忽略某些字段验证

Laravel表单请求验证忽略某些字段验证。添加和修改时,对于数据的验证有时候是不同的,如添加时要对邮箱进行唯一性验证,那么编辑时就要忽略该邮箱的唯一验证,不然将始终提示邮箱已存在。对此,官方文档仅仅只是提供了粗糙的案例,用起来并不容易。本篇文章将提供2种方法(实际上就是一种方法的延伸)。

添加和修改时,对于数据的验证有时候是不同的,如添加时要对邮箱进行唯一性验证,那么编辑时就要忽略该邮箱的唯一验证,不然将始终提示邮箱已存在。对此,官方文档仅仅只是提供了粗糙的案例,用起来并不容易。本篇文章将提供2种方法(实际上就是一种方法的延伸)。

问题

问题具体描述,如有2个页面,add.blade.php与edit.blade.php。

对于上述情况,有两种解决,

1)写2个表单请求验证,如UsAddRequest.phpUsUpdateRequest.php分开独立验证。缺点是多写文件,代码重复,优点是清晰;

2)手动实现一个场景验证。缺点就是代码多,优点是文件少。

本文将记录2)种方法实现。实际上,两种方法是一致的,只是将1)种方法的逻辑融合到2)种,然后分离出场景验证。

Laravel过滤表单验证及手动场景验证

以User模块为假设,路由、控制器、模板页面请自行创建。对于添加就不多说了,重点在于编辑界面。

第一步:定义路由

处理更新

Route::put(‘/update/{id}’,‘UserController@update’);

第二步:控制器方法、请求验证、界面自行创建

第三步:过滤表单请求验证

说明:添加与更新都使用UserReqest.php验证。

3.1、UserController控制器方法

// 添加
public function store(UserRequest $request){}
// 更新
public function update(UserRequest $request){}

3.2、UserRequest.php验证实现

namespace App\Http\Requests;

use Illuminate\Foundation\Http\FormRequest;
class UserRequest extends FormRequest
{
 // 将验证规则分离为属性
 protected $msg = [
 'username.required'     =>  '用户名必须填写',
 'email.unique'          =>  '邮箱已存在'
 ];

 public function authorize()
 {
 return true;
 }

 // 验证规则
 public function rules()
 {
 return $this->scene();
 }

 // 错误信息
 public function messages()
 {
 return $this->msg;
 }

 // 验证场景
 protected function scene()
 {
 // 接收当前路由参数
 $id = $this->route('id');
 // 请求方法
 $requestMethod = $this->method();
 // 判断是添加还是更新
 if ($requestMethod == 'POST') {
 // 添加操作
 return [
 'username'  =>  'required',
 'email'     =>  'required|email|unique:users'
 ];
 } else if ($requestMethod == 'PUT') {
 // 删除不需要的错误信息
 unset($this->msg['password.required']);
 unset($this->msg['password.min']);
 // 更新操作
 return [
 'email'     =>  'required|email|unique:users,email,' . $id
 ];
 }
 }
}

解释:

自定义了一个scene验证场景;

scene方法体中,根据请求方法的不同来区分是添加还是更新操作;

请求类型为POST,则为添加操作,那么验证所有,请求类型为PUT则为更新操作,那么只验证email并过滤自身(不验证)。

当更新时需要注意:

$id = $this->route('id');获取的是当前路由参数Route::put('/update/{id}','UserController@update');,

验证规则:'email' => 'required|email|unique:users,email,' . $id忽略自身的验证,需要注意:可以看到有2个email,第一个email是验证邮箱格式,第二个email是过滤当前验证,'email,'.$id必须严格按照这种格式。

这样一个简单的自定义场景验证规则就完成了。

本作品采用《CC 协议》,转载必须注明作者和本文链接
《L04 微信小程序从零到发布》
从小程序个人账户申请开始,带你一步步进行开发一个微信小程序,直到提交微信控制台上线发布。
《L03 构架 API 服务器》
你将学到如 RESTFul 设计风格、PostMan 的使用、OAuth 流程,JWT 概念及使用 和 API 开发相关的进阶知识。
讨论数量: 1

我也遇到了一样的困扰,我的解决方案是通过路由名称来进行区分的。

1、新增了一个 Trait,目的是动态获取验证方法名

trait RequestValidate
{
    /**
     * Determine if the user is authorized to make this request.
     *
     * @return bool
     */
    public function authorize()
    {
        return true;
    }

    /**
     * Get the validation rules that apply to the request.
     *
     * @return array
     */
    public function rules(): array
    {
        if (method_exists($this, $this->getValidateName())) {
            return call_user_func([$this, $this->getValidateName()]);
        }

        return [];
    }

    /**
     * 动态获取验证方法名称
     *
     * @return string
     */
    protected function getValidateName(): string
    {
        return 'validate' . Str::of(request()->route()->getName())->afterLast('.')->ucfirst();
    }
}

2、然后再标准的 Request 中引入 RequestValidate,根据不用的路由逻辑添加个性化验证方法。

class SalesmanRequest extends FormRequest
{
    use RequestValidate;

    /**
     * 业务员更新验证
     * 
     * @return array
     */
    private function validateStore(): array
    {
        return [
            'wechat_user_id' => 'required|unique:bank_salesmen',
            'bank_id' => 'required',
            'user_name' => 'required|max:10',
            'phone' => [
                'required',
                'phone:CN,mobile',
                'unique:bank_salesmen'
            ],
            'hit_rate' => 'required'
        ];
    }

    /**
     * 业务员更新验证
     * 
     * @return array
     */
    private function validateUpdate(): array
    {
        return [
            'wechat_user_id' => [
                'required',
                Rule::unique('bank_salesmen')->ignore($this->route('salesman'))
                    ->where(function ($query) {
                        return $query->whereNull('deleted_at');
                    })
            ],
            'bank_id' => 'required',
            'user_name' => 'required|max:10',
            'phone' => [
                'required',
                'phone:CN,mobile',
                Rule::unique('bank_salesmen')->ignore($this->route('salesman'))
                    ->where(function($query) {
                        return $query->whereNull('deleted_at');
                    })
            ],
            'hit_rate' => 'required'
        ];
    }

    public function attributes(): array
    {
        return [
            'wechat_user_id' => '微信用户',
            'bank_id' => '银行',
            'user_name' => '姓名',
            'phone' => '手机号',
            'hit_rate' => '中签率'
        ];
    }
}
3年前 评论

讨论应以学习和精进为目的。请勿发布不友善或者负能量的内容,与人为善,比聪明更重要!