[英]Laravel how to stop validation after first error
我不知道如何在第一個錯誤發生后讓laravel validate<\/strong>停止驗證,然后只返回一個錯誤
帶有 val_ 前綴的規則是我的自定義規則。
如果pesel<\/strong>字段為空(“必需”規則),我只需要顯示pesel<\/strong>字段的錯誤(“必需”規則)有人能告訴我如何達到那個嗎?
$this->validate($request, [
'pesel'=> 'bail|required|val_pesel',
'dane_os' => 'required',
'id_project' => 'required',
'imie' => 'required|val_imie',
'nazwisko'=>'required|val_nazwisko',
'nazwisko_matki'=>'required|val_nazwisko_matki'
]);
要在第一條規則失敗時停止驗證,您應該使用bail
,引用文檔
在第一次驗證失敗時停止 有時您可能希望在第一次驗證失敗后停止對屬性運行驗證規則。 為此,請將保釋規則分配給屬性:
$this->validate($request, [
'title' => 'bail|required|unique:posts|max:255',
'body' => 'required',
]);
在本例中,如果title 屬性上的required 規則失敗,則不會檢查唯一規則。 規則將按照分配的順序進行驗證。
https://laravel.com/docs/5.5/validation
這是 github 討論https://github.com/laravel/framework/issues/4789#issuecomment-174837968
我知道這個問題很老,但我今天遇到了同樣的問題,所以我將記錄我的發現:
在 Laravel 8.30.0
或更新版本中,有兩種方法可以做到:
在FormRequest類中設置以下屬性:
protected $stopOnFirstFailure = true;
手動創建一個 Validator ,並在其上調用stopOnFirstFailure(true)
方法,如下所示:
use Illuminate\Support\Facades\Validator;
$validator = Validator::make($request->all(), [
// your validation rules
])->stopOnFirstFailure(true);
$validator->validate();
要在第一個規則失敗后重定向和停止驗證,您可以使用“保釋”關鍵字。 一個例子:
// $arr = ['form input var'=>'exact word to be used in error msg'] ***
$arr = ['coverletter'=>'Cover Letter','vitae'=>'CV','certificate'=>'Certificate','tesol'=>'Tesol','photo'=>'Photo'];
// $this->validate($data,$rules,$messages);
// we have 2 rules to validate, 'required' & 'mimetypes' so output messages for them must be in an array
foreach ($arr as $k=>$v) {
if($k !== 'photo') {
// Tesol, CV, Certificate must be in PDF format so we can loop through all 3 of them here
if(!Session::get($k) || $request->$k) {
// user has submitted before but is submitting again, we evaluate the request
// user has not submitted before, we evaluate the request
$this->validate($request,
[$k => 'bail|required|mimetypes:application/pdf'],
[$k . '.required' => $v . ' is required',
$k . '.mimetypes' => $v . ' must be PDF']);
}
}
if($k == 'photo') {
if(!Session::get($k) || $request->$k) {
$this->validate($request,
[$k => 'bail|required|mimetypes:image/jpg,image/jpeg'],
[$k . '.required' => $v . ' is required',
$k . '.mimetypes' => $v . ' must be of type jpeg']);
}
}
}
這將在第一條規則失敗后重定向回您的錯誤消息。
對於那些我堅持使用 Laravel 版本< 8.30
並且無法使用@amade的解決方案的人:
您可以按如下方式擴展默認驗證器:
1. 創建一個自定義驗證器類來擴展 Laravel 驗證器並覆蓋passes
方法。
<?php
namespace App\Validation;
use Illuminate\Support\MessageBag;
use Illuminate\Validation\Validator;
class Validator extends Validator
{
protected bool $stopOnFirstFailure = false;
public function stopOnFirstFailure(bool $value = true): self
{
$this->stopOnFirstFailure = $value;
return $this;
}
// Pretty a much copy the the original code from the base class
// but added the lines around the third `break;`
public function passes()
{
$this->messages = new MessageBag;
[$this->distinctValues, $this->failedRules] = [[], []];
// We'll spin through each rule, validating the attributes attached to that
// rule. Any error messages will be added to the containers with each of
// the other error messages, returning true if we don't have messages.
foreach ($this->rules as $attribute => $rules) {
if ($this->shouldBeExcluded($attribute)) {
$this->removeAttribute($attribute);
continue;
}
foreach ($rules as $rule) {
$this->validateAttribute($attribute, $rule);
if ($this->shouldBeExcluded($attribute)) {
$this->removeAttribute($attribute);
break;
}
if ($this->shouldStopValidating($attribute)) {
break;
}
}
// ADDED LINES HERE
if ($this->stopOnFirstFailure && $this->messages->isNotEmpty())
{
break;
}
}
// Here we will spin through all of the "after" hooks on this validator and
// fire them off. This gives the callbacks a chance to perform all kinds
// of other validation that needs to get wrapped up in this operation.
foreach ($this->after as $after) {
$after();
}
return $this->messages->isEmpty();
}
}
編碼
if ($this->stopOnFirstFailure && $this->messages->isNotEmpty())
{
break;
}
將檢查是否有任何錯誤。 在這種情況下,它將跳出foreach ($this->rules as $attribute => $rules)
循環迭代屬性從而取消驗證。
如果您想在當前屬性的第一個錯誤后中斷,您仍然應該使用bail
!! 這是有意的! 否則,它將評估給定屬性的所有規則,然后停止。 您可以通過在驗證過程中遲早評估條件來更改此設置。
2. 在適當的ServiceProviter 中替換 register 方法中的 Laravel 驗證器。
<?php
namespace App\Providers;
use Illuminate\Support\ServiceProvider;
use App\Validation\Validator;
class ValidationServiceProvider extends ServiceProvider
{
/**
* Register services.
*
* @return void
*/
public function register()
{
//
}
/**
* Bootstrap services.
*
* @return void
*/
public function boot()
{
/*
* Overwrite the validator with a derived one
*/
\Validator::resolver(function ($translator, $data, $rules, $messages) {
return new Validator($translator, $data, $rules, $messages);
});
/*
* Custom validation rules
*/
\Validator::extend('my_rule', function ($attribute, $value, $parameters, $validator) {
return my_condition_helper($value);
});
}
}
3. [可選] 創建自定義FormRequest
基類:
<?php
namespace App\Http\Requests;
abstract class FormRequest extends \Illuminate\Foundation\Http\FormRequest
{
protected bool $stopOnFirstValidationFailure = false;
protected function getValidatorInstance()
{
/** @var \App\Validation\Validator $validator */
$validator = parent::getValidatorInstance();
$validator->stopOnFirstFailure($this->stopOnFirstValidationFailure);
return $validator;
}
}
當您使用FormRequest
實現派生此FormRequest
,您將能夠使用$stopOnFirstValidationFailure
屬性控制它們的行為。
用 Laravel 7 測試
您可以只使用bail
驗證規則:
// Get withdraw requests here
$data = $request->validate([
'pay_method' => 'bail|required',
'amount' => ['required', 'gte:' . (Coin::where('tick', $request->input('pay_method'))->get())->min_out, 'lte:' . $user->balance],
'receiving' => 'required|gt:0|lt:10000',
'required_data' => 'required',
'user' => 'required',
'uuid' => 'required|uuid',
'data' => 'required'
]);
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.