Laravel provides a lot of validation rules, but what if you need to add your own? We’ll show you how to do it, with the rule “max words count is 500”, and we will also make this 500 number as a parameter.

Step 1. Generate Validation Rule

From Laravel 5.5 we have ability to generate a special class where we can specify all parameters we need:

php artisan make:rule MaxWordsRule

It generates this file – app/Rules/MaxWordsRule.php:

namespace App\Rules;

use Illuminate\Contracts\Validation\Rule;

class MaxWordsRule implements Rule
{
    /**
     * Create a new rule instance.
     *
     * @return void
     */
    public function __construct()
    {
        //
    }

    /**
     * Determine if the validation rule passes.
     *
     * @param  string  $attribute
     * @param  mixed  $value
     * @return bool
     */
    public function passes($attribute, $value)
    {
        //
    }

    /**
     * Get the validation error message.
     *
     * @return string
     */
    public function message()
    {
        return 'The validation error message.';
    }
}

Step 2. Fill Validation Rule and Error Message

We need to fill in our implementation of those methods above. Method passes() should return true/false depending on value, and message() should return error message, and it may use :attribute inside of the string.

public function passes($attribute, $value)
{
    return str_word_count($value) <= 500;
}

public function message()
{
    return 'The :attribute cannot be longer than 500 words.';
}

Step 3. Calling Rule from Request Class

For validation I personally like to use Request classes, so in my app/Http/Requests/StoreCompanyRequest.php file, for example, I may use our new rule like this:

use App\Rules\MaxWordsRule;
use Illuminate\Foundation\Http\FormRequest;

class StoreCompanyRequest extends FormRequest
{

    public function rules()
    {
        return [
            'name'          => [
                'required',
            ],
            'description' => [
                new MaxWordsRule(),
            ]
        ];
    }
}

Also, notice I like to use arrays of validation rules instead of just string like 'name' => 'required', it's a totally personal preference.

And that's it, if we put in longer than 500 words description, we get error: "The description cannot be longer than 500 words".


Step 4. Bonus: Make Words Count as Parameter

Have you noticed that our Rule class has a generated empty __construct() method? This is exactly what we will use to pass a parameter to our rule. In this way, you may choose to have 500 words max for one field, but only 100 words max for another field.

Changes in Rule class:

class MaxWordsRule implements Rule
{

    private $max_words;

    /**
     * Create a new rule instance.
     * @param integer $max_words
     *
     * @return void
     */
    public function __construct($max_words = 500)
    {
        $this->max_words = $max_words;
    }

    /**
     * Determine if the validation rule passes.
     *
     * @param  string  $attribute
     * @param  mixed  $value
     * @return bool
     */
    public function passes($attribute, $value)
    {
        return str_word_count($value) <= $this->max_words;
    }

    /**
     * Get the validation error message.
     *
     * @return string
     */
    public function message()
    {
        return 'The :attribute cannot be longer than '.$this->max_words.' words.';
    }
}

As you can see, we've created a private class property $max_words and set the value in constructor. After that, we can use the value as $this->max_words everywhere inside the class.

Change in how we're calling the rule:

public function rules()
{
    return [
        'short_description' => [
            new MaxWordsRule(100),
        ]
        'description' => [
            new MaxWordsRule(), // defaults to 500
        ]
    ];
}