Reputation: 61
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 ......
Upvotes: 2
Views: 2235
Reputation:
You don't put all the validation logic in the rules method like that. Only the rule definitions go there. All you need is this:
public function rules()
{
return [
'nom' => 'required',
'ville'=> 'required|exists:villes,nom',
];
}
Laravel will handle the validation from there on out. You don't need to manually create a Validator
class when using FormRequests
.
Customizing the message involves creating a messages
method within the class like so:
public function messages()
{
return [
'depart.required' => 'Deux villes portent le même nom, preciser le départemen'
];
}
Update
As for the sometimes
rule, I'd suggest creating a Rule object and customizing how you need to check for 2 vills having the same name.
Upvotes: 0
Reputation: 5973
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.
Upvotes: 1