DEV Community

Samfield Hawb
Samfield Hawb

Posted on

The Wonders of Laravel Validation Rule Class

Hello reader, I am here once again. I want to talk about form handling with laravel Rule class (Illuminate\Validation\Rule), When it comes to handling forms in our applications, validations of inputs from users becomes a paramount thing to ensure that users don't enter invalid data in our forms.

Laravel out of the box offers us classes and methods to enable us to validate these inputs without much stress and logical thinking. If you are reading this, you're likely a professional or beginner when it comes to using laravel framework and I wrote this article just for you.

I will not be going deep to review laravel validations in this article, for more understanding you can check on the laravel documentation on validation, but in this article, I will be taking you through on how to use the Rule class to enhance your validation logic.

Laravel validation Rule class offers developers the ability to perform complex validations on user input without having to worry about the complex implementations of the classes or methods or worry about implementing it themselves. When I explored this class, I was so amazed by all that can be achieved with it.

I will be working with two tables for illustration,users and posts tables, with the following few structures.
users

id name email password
1 Samfield Hawb samfield4sure@gmail.com 3hyev4yeuh22wyu4h2y3u3

posts

id title content category user_id
1 My Title my content news 1

Let's say it happens that we want to create a new post for a user, but we need all post titles to be unique. That means no user can use a title that already exists in the database, we can run a validation on the posts table to check if the entered title already exists, if it does we reject the title and show the necessary error to the user.

public function store(Request $request){
    $input = $request->all();

    $validator = Validator::make($input, [
                'title' => [
                    "required",
                    Rule::unique('posts');
                ]
            ]);
}

Here we are using the validator make method to validate our input data. the make() method accepts two parameters, the input we want to validate and the second parameter is our validation rules. taking a look at our validation rule, we are checking the title and ensuring that the user enters the title, looking at the title rule, I supplied an array of values ['required', Rule::unique('posts')]. When using the Rule class you will need to supply an array of rules if you are combining with regular string validation,(note I ignored a second parameter to our unique method because the title matches a column on the table if we had a different column name I will supply a second parameter to indicate the column we are validating on) but it looks unusual to what most of us know which is:

  'title' => 'required|unique:posts,title'

Many will say why don't I use this since its very simple than the above, yes you are very correct, but what if I want a situation where every user can create a post with any title provided that the user has not created a post on that title, that is, post titles are unique to a user.

use Illuminate\Validation\Rule;

public function store(Request $request){
    $input = $request->all();

    $validator = Validator::make($input, [
                'title' => [
                    "required",
                    Rule::unique('posts')->where('user_id', auth()->user()->id);
                ]
            ]);
}

As you can see, we added a where clause to our Rule query builder to check only for the logged-in user, this would have been a little difficult crafting that in the above method.
Let's say we want to now update this post, but it happens that the title does not change, we can do this:

use Illuminate\Validation\Rule;

public function update($id,Request $request){
    $input = $request->all();

    $validator = Validator::make($input, [
                'title' => [
                    "required",
                    Rule::unique('posts')->where('user_id', auth()->user()-id)->whereNot('id',$id);
                ]
            ]);
}

you can see the whereNot clause we applied here to ensure that the title, even if it's unique to the user, when updating the rule does not check the id we are updating. Whao, isn't it amazing?

Rule Methods

The Rule class offers the following static methods which can be chained to achieve the validation rule we can ever imagine

Unique

The unique method accepts two parameters, table_name as the first and table_column as a second optional parameter which can be gotten from the field if it matches the column on the database table.

Exists

The Exists method ensures that the field under validation must exist on a given database table. Like the unique method, it also accepts two parameters,table_name and table_column which is also optional, if not provided the field under validation is used.

use Illuminate\Validation\Rule;

Validator::make($data, [
    'email' => [
        'required',
        Rule::exists('staff')->where(function ($query) {
            $query->where('account_id', 1);
        }),
    ],
]);

Dimension

The dimension method is used with images to ensure that the uploaded image matches a particular rule

use Illuminate\Validation\Rule;

Validator::make($data, [
    'avatar' => [
        'required',
        Rule::dimensions()->maxWidth(1000)->maxHeight(500)->ratio(3 / 2),
    ],
]);

In

The In method validate the field across given list of values in an array, in example below, I am checking the category field in my form to ensure it matches this array of categories.

Validator::make($data, [
    'category' => [
        'required',
        Rule::in(['news', 'article']),
    ],
]);

NotIn

The NotIn method validate the field across given list of values an array,in example below, I am checking the category field in my form to ensure it is not in this array of categories.

Validator::make($data, [
    'category' => [
        'required',
        Rule::notIn(['news', 'article']),
    ],
]);

RequiredIf

This method accepts a boolean or a Closure. When passed a Closure, the Closure should return true or false to indicate if the field under validation is required:

Validator::make($request->all(), [
    'role_id' => Rule::requiredIf(function () use ($request) {
        return $request->user()->is_admin;
    }),
]);

Ignore

This method is used to force the validation rule to ignore a given idduring the validation. But a second parameter can be passed to this method if our table is using a different primary key name.


use Illuminate\Validation\Rule;

public function update($id,Request $request){
    $input = $request->all();

    $validator = Validator::make($input, [
                'title' => [
                    "required",
                    Rule::unique('posts')->where('user_id', auth()->user()-id)->ignore($id /*, custom_column_name as second parameter*/);
                ]
            ]);
}

Where

This method is an addition method that can be use to perform additional query constraint like

'email' => Rule::unique('users')->where(function ($query) {
    return $query->where('account_id', 1);
})

This method accepts two parameters or a closure.

'email' => Rule::unique('users')->where('role_id', 1)

One thing I will like you to note is that the Rule class static methods always return a reference to itself. That is why its possible to chain methods to arrive at a complex rule for your input validation, for example in the code below.

 $validator = Validator::make($input, [
                'title' => [
                    "required",
                    Rule::unique('posts')->where('user_id', auth()->user()->id)->ignore(1);
                ]
            ]);
}

Conclusion

We have so far since the Rule class and the methods it provides for us to use to perform complex validations in our application, I believe you learn a lot. Follow me to get updates on my articles on Laravel as you learn a lot laravel.

Top comments (1)

Collapse
 
franciscocaldeira profile image
Francisco

now with laravel 10 is very different