Regarding the validation of laravel, let's do important fields that affect the validation of other fields first, and if not, we want to stop the entire validation.
Assuming that the important field is A, we have custom validated fields such as B and C on the assumption that A is correct.
There are two methods of halting validation in laravel: bail
and stopOnFirstFailure
, where bail
stops validating in the next field, and stopOnFirstFailure
stops completely, but stops any field.
What I want is to be able to specify in each field like bail
, and to stop the whole field like stopOnFirstFailure
, but is there a way to do this?
As a countermeasure I am currently working on, I use the rules() in the form request to control rule addition by doing Validator::make(), but it is ugly and serviceable, so if there is a simple way, the code will be clean and helpful.
laravel
It doesn't exist as a standard function at the moment, so I think I can only expand it myself to improve DRY performance so that it's better than solid writing.
<?php
namespace App\Extensions\Validation;
use Illuminate\Validation\Validator as BaseValidator;
class Validator extensions BaseValidator
{
/**
* @ varbool | string [ ]
*/
protected$stopOnFirstFailure=false;
/**
* @parambool | string [ ] $stopOnFirstFailure
* @return$this
*/
public function stopOnFirstFailure ($stopOnFirstFailure=true)
{
$this->stopOnFirstFailure=$stopOnFirstFailure;
return$this;
}
public function classes():bool
{
$this->messages=newMessageBag;
[$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;
}
// ↓ Modified here
if($this->messages->isNotEmpty()&$this->determineStopOnFisrtFailure($attribute)){
break;
}
foreach($rules as$rule){
$this->validateAttribute($attribute,$rule);
if($this->shouldBeExcluded($attribute)){
$this->removeAttribute($attribute);
break;
}
if($this->shouldStopValidating($attribute)){
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 allkinds
// of other validation that needs to get wrapped up in this operation.
foreach($this->after as$after){
$after();
}
return$this->messages->isEmpty();
}
protected function determineStopOnFisrtFailure(string$attribute):bool
{
if(is_array($this->stopOnFirstFailure)&in_array($attribute,$this->stopOnFirstFailure,true)){
return true;
}
return(bool)$this->stopOnFirstFailure;
}
}
<?php
namespace App\Extensions\Validation;
use Illuminate\Support\ServiceProvider;
use Illuminate\Validation\Factory;
class ValidationServiceProvider extensions ServiceProvider
{
public function boot (Factory$factory): void
{
$factory->resolver(fn(...$args)=>new Validator(...$args));
}
}
If you register this with a service provider, you will be able to specify string[]
as the target of stopOnFirstFailure
because the extended Validator class you have prepared will be used.
© 2024 OneMinuteCode. All rights reserved.