Laravel – Manually Invalidate A Validation
Laravel provides a nice extensible and easy validation class to validate user inputs but Sometimes we may need to forcefully invalidate a passed validation. For example, a few days ago I realized that in one of my projects. I had a table with fields group_name
and name
along with other fields and when inserting data into this table I was checking for unique group_name
but not unique name
because, same name could be available in multiple groups but there was a problem with this requirement and it was that, one group can’t contain same name twice and I couldn’t use unique
rule for the name
field because several groups may contain same name. To solve this problem I just manually checked the name
field with group_name
filed like:
$hasName = Settings::where('group_name', $groupName)->where('name', $name)->get()->count();
This code gives me an integer (1) if it found a name
under the group_name
supplied in where clause and false when the name
doesn’t exist with the group_name
and this way I can determine whether there is any name exists under same group but this is not a very big deal. The problem was to show an error message for the name
form field in the form and I didn’t extend the validator
to add a custom rule, just trying to do it in a shortcut way. So, to show the error message on the form for the appropriate form field, I just added an error message in the validator’s messaage collection and redirected back to the form (previous route) using Redirect::back()
method with validator
instanse and inputs, like:
$rules = ['group_name' => 'required', 'name' => 'required']; $validation = Validator::make($inputs, $rules, $messages); if($validation->passes()) { // normal validation passed, now check the name field $hasName = Settings::where('group_name', $groupName)->where('name', $name)->get()->count(); if($hasName) { // Add an error message in the message collection (MessageBag instance) $validation->getMessageBag()->add('name', 'Name already exists!'); // redirect back with inputs and validator instance return Redirect::back()->withErrors($validation)->withInput(); } else { // OK, name doesn't exist, save it } }
That’s it. After adding an error message in the message collection (Symfony MessageBag instance) I manually redirected back to the form and error message displayed for the name
field, telling that, “Name already exists!”. Well, this is a shortcut hacky way to do this and it may possible by extending the validator using a custom rule but I used this shortcut.
Here, getMessageBag()
public method of Illuminate\Laravel\Validator
class returns the Protected
variable $messages
and this variable is an instance of Illuminate\Support\MessageBag
which has this add()
method along with other methods and the first parameter in the add()
method is the name of the form field, for which I want to show the error message and the second parameter is the message for that field.
By default in the view $errors
variable is available and if there is any error messages found in this variable assigned against any form field name using an associative array then Laravel shows that error message for that field where $errors->first('name')
is found and I had the following on my form
{{ Form::text('name', Input::old('name')) }} {{ $errors->first('name') }}
Here $errors->first('name')
will show the first error message found in the $errors
against the name
field, which would look something like this
Illuminate\Support\MessageBag Object ( [messages:protected] => Array ( [name] => Array ( [0] => Name already exists ! ) ) [format:protected] => :message )
So, the thing is very simple, manually add an error message into $messages
and redirect back with validator and inputs. After adding the message manually, the validation still passes but the error message will be displayed for the appropriate form field that was set.
Update:
This is also possible using exists
rule with additional field name to check in where
clause like this:
'name' => 'exists:settings,name,group_name,' . $groupName
The rule given above will check if the submitted name
(in the name field) exists in the settings
table where group_name = $groupName
and no need to set the message manually but this article demonstrates how to use MessageBag
instanse to set a message manually.