How to customize error messages in Request Validation?

Laravel 5 has an awesome new function – Request Validation. It separates the logic of Validation into kind of a separate layer – Requests, which reside in the folder app/Http/Requests. After the form validation, it auto-magically shows error messages. But what if we want to customize them?

How Request Validation works

Let’s start with a reminder how this thing actually works.

1. In the View we create our Form with fields – this is a really simplified example:

{!! Form::open(['route' => 'users.store']) !!}
{!! Form::text('name', old('name'), ['placeholder' => 'Name']) !!}
{!! Form::submit('Save') !!}
0713_requests_01

2. We create a new Request class in the folder app/Http/Requests – let’s call it CreateUserRequest.php:

namespace App\Http\Requests;

use App\Http\Requests\Request;

class CreateUserRequest extends Request {

	/**
	 * Determine if the user is authorized to make this request.
	 *
	 * @return bool
	 */
	public function authorize()
	{
		return true;
	}

	/**
	 * Get the validation rules that apply to the request.
	 *
	 * @return array
	 */
	public function rules()
	{
		return [
			'name' => 'required'
		];
	}

}

The only custom line of code from empty Request class I wrote here is ‘name’ => ‘required’ – that’s the field and the rule that we need to validate.

3. In the Controller method for store() we have a new parameter – the same Request class we’ve just created:

public function store(CreateUserRequest $request) { ...

4. And that’s it – Laravel takes care of the rest of the validation – if the field isn’t filled, it would redirect back to the form with $errors variable, which we need to show:

@if ($errors->any())
    <ul>{!! implode('', $errors->all('<li style="color:red">:message</li>')) !!}</ul>
@endif

5. The result would look something like this:

0713_requests_02
Want more articles like this every week? Subscribe!




Still not sure? Want to check out past newsletter issues?
Here they are – just click this link!

So, how to customize error messages?

Now, imagine if you want to change that “The name field is required” message to your own one. Or even translate it to another language. How do you do that in Laravel?

Good thing is you don’t have to change anything in your Controllers, Requests or, in fact, /app folder at all – all messages customization is already separated into resources/lang/en/validation.php file (isn’t Laravel awesome?). Or you can create your own language folder instead of /en/.

Here’s how that file looks by default:

return [

    /*
    |--------------------------------------------------------------------------
    | Validation Language Lines
    |--------------------------------------------------------------------------
    |
    | The following language lines contain the default error messages used by
    | the validator class. Some of these rules have multiple versions such
    | as the size rules. Feel free to tweak each of these messages here.
    |
    */

    'accepted'             => 'The :attribute must be accepted.',
    'active_url'           => 'The :attribute is not a valid URL.',
    'after'                => 'The :attribute must be a date after :date.',
    'alpha'                => 'The :attribute may only contain letters.',
    'alpha_dash'           => 'The :attribute may only contain letters, numbers, and dashes.',
    'alpha_num'            => 'The :attribute may only contain letters and numbers.',
    'array'                => 'The :attribute must be an array.',
    'before'               => 'The :attribute must be a date before :date.',
    'between'              => [
        'numeric' => 'The :attribute must be between :min and :max.',
        'file'    => 'The :attribute must be between :min and :max kilobytes.',
        'string'  => 'The :attribute must be between :min and :max characters.',
        'array'   => 'The :attribute must have between :min and :max items.',
    ],
    'boolean'              => 'The :attribute field must be true or false.',
    'confirmed'            => 'The :attribute confirmation does not match.',
    'date'                 => 'The :attribute is not a valid date.',
    'date_format'          => 'The :attribute does not match the format :format.',
    'different'            => 'The :attribute and :other must be different.',
    'digits'               => 'The :attribute must be :digits digits.',
    'digits_between'       => 'The :attribute must be between :min and :max digits.',
    'email'                => 'The :attribute must be a valid email address.',
    'filled'               => 'The :attribute field is required.',
    'exists'               => 'The selected :attribute is invalid.',
    'image'                => 'The :attribute must be an image.',
    'in'                   => 'The selected :attribute is invalid.',
    'integer'              => 'The :attribute must be an integer.',
    'ip'                   => 'The :attribute must be a valid IP address.',
    'max'                  => [
        'numeric' => 'The :attribute may not be greater than :max.',
        'file'    => 'The :attribute may not be greater than :max kilobytes.',
        'string'  => 'The :attribute may not be greater than :max characters.',
        'array'   => 'The :attribute may not have more than :max items.',
    ],
    'mimes'                => 'The :attribute must be a file of type: :values.',
    'min'                  => [
        'numeric' => 'The :attribute must be at least :min.',
        'file'    => 'The :attribute must be at least :min kilobytes.',
        'string'  => 'The :attribute must be at least :min characters.',
        'array'   => 'The :attribute must have at least :min items.',
    ],
    'not_in'               => 'The selected :attribute is invalid.',
    'numeric'              => 'The :attribute must be a number.',
    'regex'                => 'The :attribute format is invalid.',
    'required'             => 'The :attribute field is required.',
    'required_if'          => 'The :attribute field is required when :other is :value.',
    'required_with'        => 'The :attribute field is required when :values is present.',
    'required_with_all'    => 'The :attribute field is required when :values is present.',
    'required_without'     => 'The :attribute field is required when :values is not present.',
    'required_without_all' => 'The :attribute field is required when none of :values are present.',
    'same'                 => 'The :attribute and :other must match.',
    'size'                 => [
        'numeric' => 'The :attribute must be :size.',
        'file'    => 'The :attribute must be :size kilobytes.',
        'string'  => 'The :attribute must be :size characters.',
        'array'   => 'The :attribute must contain :size items.',
    ],
    'timezone'             => 'The :attribute must be a valid zone.',
    'unique'               => 'The :attribute has already been taken.',
    'url'                  => 'The :attribute format is invalid.',

    /*
    |--------------------------------------------------------------------------
    | Custom Validation Language Lines
    |--------------------------------------------------------------------------
    |
    | Here you may specify custom validation messages for attributes using the
    | convention "attribute.rule" to name the lines. This makes it quick to
    | specify a specific custom language line for a given attribute rule.
    |
    */

    'custom' => [
        'attribute-name' => [
            'rule-name' => 'custom-message',
        ],
    ],

    /*
    |--------------------------------------------------------------------------
    | Custom Validation Attributes
    |--------------------------------------------------------------------------
    |
    | The following language lines are used to swap attribute place-holders
    | with something more reader friendly such as E-Mail Address instead
    | of "email". This simply helps us make messages a little cleaner.
    |
    */

    'attributes' => [],

];

Basically, it’s multi-dimensional array of text constants, with some variable prefixed by colon sign – like :attribute, :min, :max, :size etc. So it works this way:

  • Laravel searches for a rule we described in our Request class – for example ‘required’
  • We found it in the main array:
    'required' => 'The :attribute field is required.',
  • Laravel replaces :attribute with a field name (in our case ‘name’) and returns the result as string.

Once again – results then looks like this:

0713_requests_02

Now, back to the main question – if you want to customize it, you have such options:

Option 1. Change REQUIRED rule error text

You can change that ‘required’ text ‘The :attribute field is required.’ to whatever you want, and then that new text will be applied to all fields in all forms with the rule ‘required’.

// ...
    'required' => 'Please enter your :attribute.',
// ...

Option 2. Specify FIELD and RULE error text

See that ‘custom’ array at the bottom? You can add a field there and specify error text for the name of that field (in our case ‘name’) and for specific rule – it will be applied to all forms that have that particular field in it.

// ...
    'custom' => [
        'name' => [
            'required' => 'Please enter your first name',
        ],
    ],
// ...

As you can see, here you don’t have to use :attribute placeholder – cause you’re specifying exact attribute name already.

So you can add your custom messages one by one here, or add only some of them, and leave all the rest as default values, it’s up to you.

Lastly, translations into a different language

I’ve briefly mentioned already that you can add your own language. It is as simple as copy-pasting the whole /resources/lang/en/ folder to your new language, for example /resources/lang/fr/. The only tricky part is how do you define which language is active? It’s set in configuration file config/app.php:

	/*
    |--------------------------------------------------------------------------
    | Application Locale Configuration
    |--------------------------------------------------------------------------
    |
    | The application locale determines the default locale that will be used
    | by the translation service provider. You are free to set this value
    | to any of the locales which will be supported by the application.
    |
    */

    'locale' => 'en',
    // ...

And if you want to change your active language according to URL (for example, if you have website.com/fr/some_page) or other session variable (like a particular visitor settings), you can change it on the fly like this:

app()->setLocale('fr');

Or this:

app()->setLocale(Session::get('locale'));

You can put this code somewhere in your Middleware filters – here’s Laracasts forum discussion about this topic.

So that’s it, make sure your website visitors see proper and understandable error messages!

Like our articles?
Check out our Laravel online courses!

5 COMMENTS

  1. Hey,

    Do you know it’s also possible to set custom attributes at the request class itself by overriding the: attributes() function. This can be useful to set a custom attribute name for one particular request. It can be that your attribute doesn’t change when using this. That’s then probably because your ValidationService resolver need te be aware of the customAttributes. Search for “Validator::resolver” and add the $attributes to the method call like this:

    Validator::resolver(function($translator, $data, $rules, $messages, $attributes)
    {
    return new ValidatorService($translator, $data, $rules, $messages, $attributes);
    });

LEAVE A REPLY

Please enter your comment!
Please enter your name here