4
votes

I use made use the extend function to extend and adding custom rules on the Validation Class of Laravel 4.

Validator::extend('foo', function($attribute, $value, $parameters)
{
    return $value == 'foo';
});

When I validate the rule using the newly created custom extension, it returns validation.foo if the rule fails. Is there a way to define a generic/ default message when extending the validation class in Laravel 4?

3

3 Answers

9
votes

The Laravel 4 docs specifically state you need to define an error message for your custom rules.

You have two options;

Option 1:

$messages = array(
    'foo' => 'The :attribute field is foo.',
);

$validator = Validator::make($input, $rules, $messages);

Option 2:

Specify your custom messages in a language file instead of passing them directly to the Validator. To do so, add your messages to custom array in the app/lang/xx/validation.php language file:

'custom' => array(
    'foo' => array(
        'required' => 'We need to know your foo!',
    ),
),
1
votes

In case someone is wondering about Laravel 5: just add your message to validation.php right under all the default messages. For example:

<?php

return [
// .. lots of Laravel code omitted for brevity ...

"timezone"             => "The :attribute must be a valid zone.",

/* your custom global validation messages for your custom validator follow below */

"date_not_in_future"          => "Date :attribute may not be in future.", 

where date_not_in_future is your custom function validateDateNotInFuture. Laravel will pick the message each time you use your rule for any field and you won't have to use custom array unless you want to override your global message for specific fields.

Full code to implement the validator follows.

Custom Validator (with a bonus gotcha comments for date_format and date_before localization):

<?php namespace App\Services\Validation;

use Illuminate\Validation\Validator as BaseValidator;

/**
 * Class for your custom validation functions
 */
class Validator extends BaseValidator  {

    public function validateDateNotInFuture($attribute, $value, $parameters)
    {
        // you could also test if the string is a date at all 
        // and if it matches your app specific format 
        // calling $this->validateDateFormat validator with your app's format 
        // loaded from \Config::get, but be careful - 
        // Laravel has hard-coded checks for DateFormat rule 
        // to extract correct format from it if it exists, 
        // and then use for validateBefore. If you have some unusual format
        // and date_format has not been applied to the field,
        // then validateBefore will give unpredictable results.
        // Your best bet then is to override protected function 
        // getDateFormat($attribute) to return your app specific format

        $tomorrow = date('your app date format here',  strtotime("tomorrow"));

        $parameters[0] = $tomorrow;
        return $this->validateBefore($attribute, $value, $parameters);
    }
}

ValidatorServiceProvider file:

<?php namespace App\Providers;

namespace App\Providers;

use App\Services\Validation\Validator;
use Illuminate\Support\ServiceProvider;

class ValidatorServiceProvider extends ServiceProvider{

    public function boot()
    {
        \Validator::resolver(function($translator, $data, $rules, $messages)
        {
            return new Validator($translator, $data, $rules, $messages);
        });
    }

    public function register()
    {
    }
}

And then just add a line to config/app.php:

    'App\Providers\RouteServiceProvider',
    'App\Providers\ValidatorServiceProvider', // your custom validation  
0
votes

In addition to what TheShiftExchange has said, if you look in that validation.php language file you'll see all of the different rules that you can specify. So for instance, if your validator has entries like this:

class ArticleValidator extends Validator
{
    public static $rules = [
        'create'    => [
            'title'                     => ['required'],
            'slug'                      => ['required', 'regex:([a-z\0-9\-]*)']
        ]
    ];

}

Then your custom validation rules may look like this:

'custom' => array(
    'company_article_type_id' => array(
        'required' => 'The slug field is really important',
        'exists' => 'The slug already exists',
    ),
),

Notice how the 'required' and 'exists' keys in the custom validation rules match those in the validator above.