65.9K
CodeProject 正在变化。 阅读更多。
Home

如何在 Laravel 项目中创建自定义表单请求验证

starIconstarIconstarIconstarIconstarIcon

5.00/5 (1投票)

2021 年 1 月 15 日

CPOL

3分钟阅读

viewsIcon

27499

本教程介绍了如何在 Laravel(5.8 或 6+)项目中创建和使用自定义表单请求验证。

引言

本教程介绍了如何在 Laravel(5.8 或 6+)项目中创建和使用自定义表单请求验证。Laravel 中验证表单提交数据有几种方法。

控制器中的直接验证

标准方法是在控制器的开头直接使用 Validator facade。 让我们看一个例子

/**
 * Store a newly created resource in storage.
 *
 * @param \Illuminate\Http\Request $request
 * @return \Illuminate\Http\Response
 */
public function store(Request $request)
{
    $validator = Validator::make($request--->all(), [
        "title"  => "required|min:5|max:200",
        "body_content"=> "required|min:10",
        "blog_tag_id" => "nullable",
    ],[
        "title.required" => "Please write a title",
        "title.min" => "The title has to have at least :min characters.",
        "title.max" => "The title has to have no more than :max characters.",
        "body_content.required" => "Please write some content",
        "body_content.min" => "The content has to have at least :min characters",
    ]);

    // ... next part of code after validation
}

如您在此示例中所见,我们在控制器的 action 中执行验证。这看起来还不错,直到您想在其他地方使用相同的代码:例如,在后端创建帖子,或者您想添加单元测试。在这种情况下,您将复制粘贴相同的代码片段,这不好,因为您必须维护所有这些代码,并且这种编程风格违反了 DRY 原则(不要重复自己)。

使用自定义验证器

那么... 实现这种验证的更好方法是什么? Laravel 允许我们创建自己的 Request 类,而不是使用标准的 \Illuminate\Http\Request 并将其作为函数参数使用。 让我们看看如何做到这一点。

首先要做的是创建此类。 运行以下命令

$ php artisan make:request App\Http\Requests\MyOwnRequest

此命令将在 App\Http\Requests\ 目录中创建 MyOwnRequest 请求类。 默认情况下,它将如下所示

namespace App\Http\Requests\Auth;

use Illuminate\Foundation\Http\FormRequest;

class MyOwnRequest extends FormRequest
{
    /**
     * Determine if the user is authorized to make this request.
     * @return bool
     */
    public function authorize()
    {
        return false;
    }

    /**
     * Get the validation rules that apply to the request.
     * @return array
     */
    public function rules()
    {
        return [
            //
        ];
    }
}

现在您可以将验证规则移动到那里,并将 store() 方法中的 Request 参数替换为 MyOwnRequest

您的控制器 store() 方法将如下所示

/**
 * Store a newly created resource in storage.
 *
 * @param \Illuminate\Http\MyOwnRequest $request
 * @return \Illuminate\Http\Response
 */
public function store(MyOwnRequest $request)
{
 
    // ... next part of code after validation
}

MyOwnRequest 类将如下所示
(请记住将 authorize() 方法的返回值设置为 TRUE!)

namespace App\Http\Requests\Auth;

use Illuminate\Foundation\Http\FormRequest;

class MyOwnRequest extends FormRequest
{
    /**
     * 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()
    {
        return [
           "title"  => "required|min:5|max:200",
           "body_content"=> "required|min:10",
           "blog_tag_id" => "nullable",
        ];
    }
}

看起来好多了,对吧?

请求类的自定义

自定义消息

现在,如果您想指定自定义验证消息怎么办? 可以使用验证器类的 messages() 方法轻松实现。 您只需定义一个数组,其中键是字段名称,值是您想要显示的自定义消息。

namespace App\Http\Requests\Auth;

use Illuminate\Foundation\Http\FormRequest;

class MyOwnRequest extends FormRequest
{
    /**
     * 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()
    {
        return [
            "title"  => "required|min:5|max:200",
            "body_content"=> "required|min:10",
            "blog_tag_id" => "nullable",
        ];
    }

    /**
     * Custom message for validation
     *
     * @return array
     */
    public function messages()
    {
        return [
            "title.required" => "Please write a title",
            "title.min" => "The title has to have at least :min characters.",
            "title.max" => "The title has to have no more than :max characters.",
            "body_content.required" => "Please write some content",
            "body_content.min" => "The content has to have at least :min characters",
        ];
    }
}

字段集的验证

好的,现在看起来更好。 但是,如果您需要验证一组字段怎么办,例如:几个复选框或几个文件字段? 在这种情况下,您可以使用星号 * 来准备验证规则。 请查看下面的示例,了解我们如何定义字段集的验证规则。 我希望它足够清晰易懂。

public function rules(): array
{
   return [
      "files.*" => "required|image|mimes:jpg,jpeg,png",
      "attrs.*.from" => "nullable|numeric",
      "attrs.*.to" => "nullable|numeric",
   ];
}

属性的特殊命名

如您所知,Laravel 会自动创建验证消息,因此有时您需要为字段提供特殊名称。 您可以使用以下语言行来交换属性占位符,例如将“email”替换为“电子邮件地址”,或数组中的索引,以使消息更易于阅读。 这只是为了帮助我们使消息更简洁。

public function attributes(): array
{
   return [
      "receivers" => "Nice name",
      "subject" => "Like name",
      "body" => "Another Name",
      "notify.blog.*" => "Blog Notification value",
   ];
}

添加您自己的验证

现在,如果您想执行自己的验证,可以使用 withValidator() 方法。 当您需要在主验证通过(或未通过)后执行其他或非常复杂的验证时,它很有用。 在下面的示例中,我们检查电子邮件是否在预先批准的电子邮件列表中。 请注意,您可以使用一些方法

$validator->after()
$validator->fails()
等等。

/**
* @param  \Illuminate\Validation\Validator  $validator
* @return void
*/
public function withValidator(Validator $validator)
{
   $email = $validator->getData()['email'] ?? '';
   $validator->after(
      function ($validator) use ($email) {
         if (is_null(\DB::table('pre_approved')->where('email',$email)->first())) {
            $validator->errors()->add(
               'email',
               'This email does not exist on our pre-approved email list'
            );
         }
      }
   );                            
}

不要忘记授权

如前所述,表单请求类还包含一个 authorize 方法。 您可以检查经过身份验证的用户是否实际上有权更改给定的资源。 让我们看一个例子,当用户实际拥有博客评论并尝试更新它时

/**
 * Check if the user is authorized to make this request.
 * @return bool
 */
public function authorize()
{
   $comment = Comment::find($this->route('comment'));
   return $comment && $this->user()->can('update', $comment);
}

自定义重定向

最后,如果您想重新定义验证失败时的路由,可以通过重新定义 $redirectRoute 属性来完成。

// The named route to redirect to if validation fails.
protected $redirectRoute = 'home';

历史

  • 2021 年 1 月 15 日:初始版本
© . All rights reserved.