I want to check if a form input 'departement' is filled only if two 'villes' have the same name.
within controller this code wokds perfectly :
$rules=[ 'nom' => 'required', 'ville'=> 'required|exists:villes,nom'];
$messages = [
'depart.required' => 'Deux villes portent le même nom, preciser le
département'];
$validator = Validator::make($request->All(), $rules,$messages);
$validator->sometimes('depart_id', 'required|exists:departs,id', function
($input) {
return Ville::where('nom',$input->ville)->count()>1;
});
if ($validator->fails()) {
return redirect('admin/etab/create')
->withErrors($validator)
->withInput();
}
I put the same code in a Form Request class:
public function rules()
{
$rules=[ 'nom' => 'required', 'ville'=> 'required|exists:villes,nom'];
$messages = [
'depart.required' => 'Deux villes portent le même nom, preciser le
département',
];
$validator = Validator::make($this->All(), $rules,$messages);
$validator->sometimes('depart_id', 'required|exists:departs,id', function
($input) {
return Ville::where('nom',$input->ville)->count()>1;
});
return $validator;
}
I get "Type error: Argument 2 passed to Illuminate\Validation\Factory::make() must be of the type array, object given,"
I think error message is inadequate but I cannot find why this way does not work
Thanks ......
You can check out the FormRequest
class in vendor/laravel/framework/src/Illuminate/Foundation/Http/FormRequest.php
and check what it does.
It contains these 2 method at the top:
/**
* Get the validator instance for the request.
*
* @return \Illuminate\Contracts\Validation\Validator
*/
protected function getValidatorInstance()
{
$factory = $this->container->make(ValidationFactory::class);
if (method_exists($this, 'validator')) {
$validator = $this->container->call([$this, 'validator'], compact('factory'));
} else {
$validator = $this->createDefaultValidator($factory);
}
if (method_exists($this, 'withValidator')) {
$this->withValidator($validator);
}
return $validator;
}
/**
* Create the default validator instance.
*
* @param \Illuminate\Contracts\Validation\Factory $factory
* @return \Illuminate\Contracts\Validation\Validator
*/
protected function createDefaultValidator(ValidationFactory $factory)
{
return $factory->make(
$this->validationData(), $this->container->call([$this, 'rules']),
$this->messages(), $this->attributes()
);
}
So you can basically provide a validator
method in your own FormRequest class to create a custom Validator object, that method will get the ValidatorFactory as param.
In your case you would not need to do this, because you just want to append the sometimes
rule to a default validator. Looking at the code above, it checks for the existence of the withValidator
method, if it exists, it is called:
if (method_exists($this, 'withValidator')) {
$this->withValidator($validator);
}
You could create the FormRequest, make sure the rules
, messages
and authorize
methods are properly used, e.g. rules and messages return arrays and authorize returns a bool.
Then create a withValidator
method in which you attach the sometimes rule to the Validator.
/**
* Do foo with Validator
*
* @param \Illuminate\Contracts\Validation\Validator $validator
* @return void
*/
public function withValidator(Validator $validator)
{
$validator->sometimes('depart_id', 'required|exists:departs,id', function {
return Ville::where('nom', $this->input('ville'))->count() > 1;
});
}
This way sometimes
is attached to your validator before the validation is performed.