Laravel 编码技巧 - 验证

作者: 温新

图书: 【Laravel 编码技巧】

阅读: 184

时间: 2024-02-29 08:33:41

图片验证

在验证上传的图像时,您可以指定所需的尺寸。

['photo' => 'dimensions:max_width=4096,max_height=4096']

验证后为表单请求添加值

class UpdatedBookRequest extends FormRequent
{
     public function validated()
     {
          return array_merge(parent::validated(), [
               'user_id' => Auth::user()->id,
          ]);
     }
}

FormRequests 中的访问模型绑定

使用 FormRequests 时,只需使用以下表达式即可访问绑定模型$𝘁𝗵𝗶𝘀->{𝗿𝗼𝘂𝘁𝗲-𝗯𝗶𝗻𝗱𝗶𝗻𝗴-𝘃𝗮𝗿𝗶𝗮𝗯𝗹𝗲}

举个例子

class CommunityController extends Controller
{
     // ...
     public function update(CommunityUpdateRequest $request, Community $community)
     {
          $community->update($request->validated());

          return to_route('communities.index')->withMessage('Community updated successfully.');
     }
     // ...
}

class CommunityUpdateRequest extends FormRequest
{
     // ...
     public function rules()
     {
          return [
               'name' => ['required', Rule::unique('communities', 'name')->ignore($this->community)],
               'description' => ['required', 'min:5'],
          ];
     }
     // ...
}

确保接受另一个字段时需要验证的字段的规则

你可以使用 required_if_accepted 验证规则,该规则确保如果接受另一个字段(值为yes、on、1或true),则验证中的字段是必需的。

Validator::make([
     'is_company' => 'on',
     'company_name' => 'Apple',
], [
     'is_company' => 'required|boolean',
     'company_name' => 'required_if_accepted:is_company',
]);

自定义验证错误消息

只需在 resources/lang/xx/validation.php 文件创建适当的数组结构,就可以定义定每个 字段、规则和语言的验证错误消息。

'custom' => [
     'email' => [
        'required' => 'We need to know your e-mail address!',
     ],
],

用 now 或 yesterday 来验证日期

你可以使用 before/after 的规则验证日期,并将各种字符串作为参数传递,比如: tomorrow, now, yesterday。例如: 'start_date' => 'after:now'。它在底层下使用 strtotime ()

$rules = [
    'start_date' => 'after:tomorrow',
    'end_date' => 'after:start_date'
];

带有某些条件的验证规则

如果验证规则依赖于某些条件,则可以通过将 withValidator() 添加到 FormRequest 类中来修改规则,并在那里指定自定义逻辑。例如,如果您只想为某些用户角色添加验证规则。

use Illuminate\Validation\Validator;

class StoreBlogCategoryRequest extends FormRequest {
    public function withValidator(Validator $validator) {
        if (auth()->user()->is_admin) {
            $validator->addRules(['some_secret_password' => 'required']);
        }
    }
}

更改默认验证消息

如果要更改特定字段和特定验证规则的默认验证错误消息,只需将 messages() 方法添加到FormRequest类中。

class StoreUserRequest extends FormRequest
{
    public function rules()
    {
        return ['name' => 'required'];
    }

    public function messages()
    {
        return ['name.required' => 'User name should be real name'];
    }
}

预验证

如果你想在默认的Laravel验证之前修改某个字段,或者,换句话说,“准备” 那个字段, FormRequest 类中有一个方法 prepareForValidation ()

protected function prepareForValidation()
{
    $this->merge([
        'slug' => Illuminate\Support\Str::slug($this->slug),
    ]);
}

首次验证错误时停止

默认情况下,Laravel 验证错误将以列表形式返回,检查所有验证规则。但是,如果你想在第一个错误后停止过程,可以使用名为 bail 的验证规则:

$request->validate([
    'title' => 'bail|required|unique:posts|max:255',
    'body' => 'required',
]);

如果你需要在 FormRequest 类中在第一个错误后停止验证,可以将 stopOnFirstFailure 属性设置为 true:

protected $stopOnFirstFailure = true;

在未使用 validate() 或表单请求的情况下,抛出 422 状态代码

如果不使用 validate() 或表单请求,但仍需要使用相同的 422 状态代码和错误结构抛出错误,可以手动抛出 ValidationException::withMessages()

if (! $user || ! Hash::check($request->password, $user->password)) {
    throw ValidationException::withMessages([
        'email' => ['The provided credentials are incorrect.'],
    ]);
}

取决于其他条件的规则

如果你的规则是动态的,并且取决于某些其他条件,你可以即时创建规则数组。

    public function store(Request $request)
    {
        $validationArray = [
            'title' => 'required',
            'company' => 'required',
            'logo' => 'file|max:2048',
            'location' => 'required',
            'apply_link' => 'required|url',
            'content' => 'required',
            'payment_method_id' => 'required'
        ];

        if (!Auth::check()) {
            $validationArray = array_merge($validationArray, [
                'email' => 'required|email|unique:users',
                'password' => 'required|confirmed|min:5',
                'name' => 'required'
            ]);
        }
        //
    }

使用 Rule::when() 可以有条件地应用验证规则

感谢 Rule::when(),我们可以在 Laravel 中根据条件应用验证规则。

在这个例子中,我们仅在用户实际上可以投票帖子时才验证投票的值。

use Illuminate\Validation\Rule;

public function rules()
{
    return [
        'vote' => Rule::when($user->can('vote', $post), 'required|int|between:1,5'),
    ]
}

在请求类中使用该属性可停止验证整个请求属性

在请求类中使用此属性以停止整个请求属性的验证。

提示:直接

这与仅在单个属性的规则不验证时停止验证的 Bail 规则不同。

/**
* 指示验证器是否应该在单个规则失败后停止
* 整个验证。
 */
protected $stopOnFirstFailure = true;

unique 规则在软删除全局作用域中无效

Rule::unique 默认不在软删除的全局范围内。但是使用withoutTrashed` 时可用。

Rule::unique('users', 'email')->withoutTrashed();

Validator::sometimes() 方法允许我们定义何时应用验证规则

Laravel 的 Validator::sometimes() 方法允许我们根据提供的输入定义何时应用验证规则。

以下代码片段展示了如何禁止在购买的商品数量不足时使用优惠券:

$data = [
    'coupon' => 'PIZZA_PARTY',
    'items' => [
        [
            'id' => 1,
            'quantity' => 2
        ],
        [
            'id' => 2,
            'quantity' => 2,
        ],
    ],
];

$validator = Validator::make($data, [
    'coupon' => 'exists:coupons,name',
    'items' => 'required|array',
    'items.*.id' => 'required|int',
    'items.*.quantity' => 'required|int',
]);

$validator->sometimes('coupon', 'prohibited', function (Fluent $data) {
    return collect($data->items)->sum('quantity') < 5;
});

// 当提供的数量不足以抛出一个ValidationException异常
$validator->validate();

数组元素验证

如果你想验证你提交的数组元素,可以使用规则中的点表示法和'*'。

// 假设你有以下数组
// 请求中的数组 'user_info'
$request->validated()->user_info = [
    [
        'name' => 'Qasim',
        'age' => 26,
    ],
    [
        'name' => 'Ahmed',
        'age' => 23,
    ],
];

// 规则
$rules = [
    'user_info.*.name' => ['required', 'alpha'],
    'user_info.*.age' => ['required', 'numeric'],
];

Password::defaults 方法

在验证用户提供的密码时,可以使用 Password::defaults 方法强制执行特定规则。它包括要求输入字母、数字、符号等选项。

class AppServiceProvider
{
    public function boot(): void
    {
        Password::defaults(function () {
            return Password::min(12)
                ->letters()
                ->numbers()
                ->symbols()
                ->mixedCase()
                ->uncompromised();
        })
    }
}

request()->validate([
    ['password' => ['required', Password::defaults()]]
])

表单验证重定向请求

在使用表单请求进行验证时,默认情况下,验证错误将重定向回上一页,但你可以覆盖它。只需定义 $redirect$redirectRoute 属性即可。

文档

// 用户在验证失败时应重定向到的URI。
protected $redirect = '/dashboard';

// 用户在验证失败时应重定向到的路由。
protected $redirectRoute = 'dashboard';

Mac 验证规则

Laravel 8.77 新增 mac_address 验证规则

$trans = $this->getIlluminateArrayTranslator();
$validator = new Validator($trans, ['mac' => '01-23-45-67-89-ab'], ['mac' => 'mac_address']);
$this->assertTrue($validator->passes());

需要带域名的电子邮件

默认情况下,电子邮件验证规则将接受不带 tld 域名的电子邮件(即:taylor@laravel, povilas@ldaily)。

但如果要确保电子邮件必须有 tld 域名(即:taylor@laravel.com, povilas@ldaily.com),请使用 email:filter 规则。

[
    'email' => 'required|email', // before
    'email' => 'required|email:filter', // after
],

新的数组验证规则 required_array_keys

Laravel 8.82 新增了 required_array_keys 验证规则。该规则检查数组中是否存在所有指定的键。

通过验证的有效数据:

$data = [
    'baz' => [
        'foo' => 'bar',
        'fee' => 'faa',
        'laa' => 'lee'
    ],
];

$rules = [
    'baz' => [
        'array',
        'required_array_keys:foo,fee,laa',
    ],
];

$validator = Validator::make($data, $rules);
$validator->passes(); // true

会使验证失败的无效数据:

$data = [
    'baz' => [
        'foo' => 'bar',
        'fee' => 'faa',
    ],
];

$rules = [
    'baz' => [
        'array',
        'required_array_keys:foo,fee,laa',
    ],
];

$validator = Validator::make($data, $rules);
$validator->passes(); // false

验证消息中的位置占位符

在 Laravel 9 中,如果使用数组,可以在验证信息中使用 :position 占位符。

这将输出 "请提供价格 #2 的金额"。

class CreateProductRequest extends FormRequest
{
    public function rules(): array
    {
        return  [
            'title' => ['required', 'string'];
            'description' => ['nullable', 'sometimes', 'string'],
            'prices' => ['required', 'array'],
            'prices.*.amount' => ['required', 'numeric'],
            'prices.*.expired_at' => ['required', 'date'],
        ];
    }

    public function messages(): array
    {
        'prices.*.amount.required' => 'Please provide an amount for price #:position'
    }
}

验证值

当您需要验证一个字段,但实际上不需要它做任何事情(如 "接受条款和条件")时,请使用排除规则。这样,验证方法就不会返回该字段...

class StoreRequest extends FormRequest
{
    public function rules(): array
    {
        return [
            'name' => 'required|string',
            'email_address' => 'required|email',
            'terms_and_conditions' => 'required|accepted|exclude',
        ];
    }
class RegistrationController extends Controller
{
    public function store(StoreRequest $request)
    {
        $payload = $request->validated(); // only name and email

        $user = User::create($payload);

        Auth::login($user);

        return redirect()->route('dashboard');
    }
请登录后再评论