Close
Do you want more articles like this delivered straight to your inbox?

Subscribe now to my e-mail newsletter and get my latest articles and project updates delivered directly to your inbox. Never miss an update.

How to validate Laravel user input for beginners (2021)

Published July 23, 2021; last updated on September 10, 2021
How to validate Laravel user input for beginners (2021)

Laravel is by far the most popular PHP framework, due to its enormous flexibility, awesome community and shallow learning curve. Handling and validating user input is perhaps one of the most important things in Laravel. In this article I’ll show you the three methods for validating user input.

For this article I’ll assume you already have a form and something similar to the following two routes:

use App\Http\Controllers\PostController;

Route::get('/post/create', [PostController::class, 'create']);
Route::post('/post', [PostController::class, 'store']);

The main principle behind validation is very simple: you take some input, you define some rules to test the input against, and the validator checks whether the rules apply to the input. If not, it gives you the appropriate error message(s). Depending on the method that you use, the error messages can be automatically returned to the user or you can do that manually.

If the input is valid, it will automatically proceed as normal. This makes it very easy to just put a validation before almost every input – and prevent errors and weird things in the future.

  1. Validation method 1: $request->validate()
  2. Validation method 2: Laravel Form Requests
  3. Validation method 3: Manually making the Validator::make()

Validation method 1: $request->validate()

The first method is the method that can immediately be applied immediately on the request: $request->validate($rules). In your controller, we have something like this:

use Illuminate\Http\Request;

public function store(Request $request)
{
    $validated = $request->validate([
        'title' => 'required|unique:posts|max:255',
        'body' => 'required',
    ]);

    // The input is valid...
}

Here the following happens:

  1. We take the input in the variable $request.
  2. We apply the validate() method on it ($request->validate()).
  3. The output is saved in the variable $validated.

What happens when the validator fails?

If the validator fails, Laravel automatically redirects to the previous page. Thus the page on which is the form. On that page, Laravel inserts the variable $errors. You can use this variable to display the errors:

<!-- /resources/views/post/create.blade.php -->

<h1>Create Post</h1>

@if ($errors->any())
    <div class="alert alert-danger">
        <ul>
            @foreach ($errors->all() as $error)
                <li>{{ $error }}</li>
            @endforeach
        </ul>
    </div>
@endif

<!-- Create Post Form -->

If you want to customize the Validation error messages, the docs say the following:

Laravel’s built-in validation rules each has an error message that is located in your application’s resources/lang/en/validation.php file. Within this file, you will find a translation entry for each validation rule. You are free to change or modify these messages based on the needs of your application

What happens if the validator is successful?

If the validator is successful, it will go on to the next step in the controller.

Validation method 2: Laravel Form Requests

If you have to handle much user input, it can be useful to put the validation logic all in one place. If you’ve read the above example, you’ll soon find yourself in a situation where every controller is cluttered with a validation rules. Luckily, Laravel has a solution for that: Form Requests.

A Form Request is a separate class. If you create a Form Request for each form, you’ll organise your application much better, because all the logic is in one place. It also allows you to reuse validation rules, without having to repeat them, e.g. in two controllers. When you want to use it in your controller, you’d use an instance of your Form Request instead of an instance of the ‘regular’ Request $request.

To make a Form Request, run the following Artisan command from your project folder:

php artisan make:request StorePostRequest

The request will be placed in the following file: app/Http/Requests/StorePostRequest.php. This file includes two methods: rules() and authorize()

Form Request: the rules() method

The rules() method is the simpler method of the two: it is just a function that defines the validation rules to check against. The method is very simple, because it only returns an array with the rules:

public function rules()
{
    return [
        'title' => 'required|unique:posts|max:255',
        'body' => 'required',
    ];
}

Form Request: the authorize() method

The authorize() method is the second function in your Form Request. This function should return a boolean (true/false). In short, you can perform some sort of check if the user is allowed to submit this form. You’d want a malicious user to submit POST requests that are intended for admins only.

public function authorize()
{
    /* Retrieve the comment that the user wants to update */
    $comment = Comment::find($this->route('comment'));

    /* Check if the comment exists and if the user is allowed to update this particular comment. If you want to learn more about the user()->can() method, you should checkout the Laravel docs on guards and authorization. */
    return $comment && $this->user()->can('update', $comment);
}

How do we use Form Requests?

Using Form Requests is very simple. In your controller, use something like the below. So instead of using Request $request we use StorePostRequest $request.

use \App\Http\Requests\StorePostRequest;

public function store(StorePostRequest $request)
{
    // The incoming request is valid... 
    // else the Form Request would have returned the error messages and we wouldn't be here then.

    // Retrieve the validated input data...
    $validated = $request->validated();
}

Displaying error messages goes in the same way as with method 1.

Customize error messages in Form Request

There are some other functions for which it’s worth knowing that you can optionally add them to your Form Requests. One of those is the messages() function. It allows you to customize the error message on a per-form basis and not for your complete application at once:

public function messages()
{
    return [
        'title.required' => 'A title is required',
        'body.required' => 'A message is required',
    ];
}

Validation method 3: Manually making the Validator::make()

The third method is to manually make an instance of the Laravel Validator. This does not automatically redirect and return the error messages, but it allows you to catch and handle them how you like. It means that you get greater freedom on how to use it. Checkout the following example:

use Illuminate\Http\Request;
use Illuminate\Support\Facades\Validator;

public function store(Request $request)
{
    $validator = Validator::make($request->all(), [
        'title' => 'required|unique:posts|max:255',
        'body' => 'required',
    ]);

    if ($validator->fails()) {
        
        // For example:
        return redirect('post/create')
                ->withErrors($validator)
                ->withInput();

        // Also handy: get the array with the errors
        $validator->errors();

        // or, for APIs:
        $validator->errors()->toJson();
    }

    // Input is valid, continue...
   }

Defining the rules

As you’ve seen in the above examples, to use the validator we need to define rules. There are many, many rules, but below I’ve listed the most common rules. For a more extensive list, please refer to the documentation.

In our examples here, we’re using the ‘pipe’ syntax: 'fieldname': 'rule|otherRule|anotherRule'.
But you can also use the array syntax: 'fieldname': ['rule', 'otherRule', 'anotherRule'].

Most common Laravel Validation rules:

Requiring input:

required, required_if:anotherField,equalToThisValue, required_unless:anotherField,equalToThisValue

Fields must have certain patterns (email):

email, active_url, ip.

Databases (unqiue & existing records):

exists:tableName,columnName, unique:tableName,columnName.

Before or after certain date:

after:date, before:date. Note that date must be a string that strtotime() can work with.

Conclusion

As you’ve seen, validating (external API) data and user input in Laravel is very easy and there are a few common workflows. Each workflow has its own level of ‘working out-of-the-box’ or giving you more freedom. If there’s something unclear, you spot an error of if you just want to say hi, please leave a comment below👇

Stay up to date with all things Laravel, Tailwind, WordPress & PHP

Subscribe now to my e-mail newsletter and get my latest articles and project updates delivered directly to your inbox. Never miss an update.

Image Ralph J. Smit
Ralph is a designer gone developer. He happily lives in the Netherlands. His passion for good design drove him towards development, because he felt that no-code tools were too limiting. On this blog, Ralph writes the articles he would've wanted to have during his continual developer journey. → Follow on Twitter

Comments

Leave a reply

Your email address will not be published. Required fields are marked *