簡體   English   中英

"Laravel如何在第一個錯誤后停止驗證"

[英]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或更新版本中,有兩種方法可以做到:

1. 使用 FormRequest

FormRequest類中設置以下屬性:

protected $stopOnFirstFailure = true;

2. 使用驗證器

手動創建一個 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.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM