Making The Most Of Laravel Form Requests

damilola jolayemi
Damilola Jolayemi
Published in
6 min readOct 25, 2017

I started using form request when I noticed my controllers were starting to get large and some validation rules used in model crud operations were almost the same and I did not want to repeat them.

If you don’t know about Laravel’s form requests or haven’t been using it yet, you might be missing out on a whole lot of good. Let me show you what i know about it.

What is it?

Form requests are custom request classes that contain validation logic. You can create different requests specific to actions you want executed. Official documentation for is lives here.

How is it created?

To create a request, from the terminal, navigate to the root directory of your Laravel application and run

php artisan make:request NameOfRequest

This will generate a new request class which is placed in the app/Http/Requests directory. The directory will be created if it does not exist. The created class contains two methods, authorize and rules.

To explain the different scenarios in which i have been using form requests, we are going to build an application where an authenticated user can send messages to the admin. In a real application, this could be for many reasons including, dispute settling, support, security concerns, etc.

To get you started quickly, i have created a starting point for this application:

All you need to do is: clone the start branch, configure database details in .env file, run php artisan key:generate and run the database migrations.

If you look at the application code, specifically, in the MessagesController.php, you’ll notice we are doing all the normal stuff.

The index method shows a list of all messages we have created/sent, the new method loads the page where we input details for a new message and the create method processes it. The edit method loads the page where we change the details for an already created message and the update method processes it. In both the create and update methods, we validate the request before continuing with saving or updating. We basically have a normal application here. It’s a good starting point to talk about Laravel’s form requests.

Create Form Request

In the terminal, navigate to the root directory of your laravel app and run

php artisan make:request MessageRequest

Depending on the use case, I usually follow any of these two patterns to create a form request:

php artisan make:request {{Modelname}}Requestorphp artisan make:request {{Modelname}}{{Action}}Request

The created class contains two methods; authorize and rules. For now, change the authorize method to return true.

Validation

For validation, we are concerned about the rules method. Inside of it we can get the validation rules that apply to the request. In our message application, before a message is created, we would check the incoming request to validate if it contains the required inputs. Right now the validation is in the Messagescontroller, we are gonna move the rules from the controller to MesssageRequest.php

//MessageRequest.phppublic function rules(){return [    'email' => 'required|email|max:50',    'category' => 'required',    'subject' => 'required|max:100',    'message' => 'required|max:500'];}

Next in our controller we would import the MessageRequest class, type-hint it in our create method and delete all validation code in the method.

//MessagesController.php 
use App\Http\Request\MessageRequest;
public function create(MessageRequest $request){ Message::create($request->validated()); return back()->with('successfulCreate', 'Successful create operation.');}

Now if you try to create a message, the incoming request is validated before the create method is called, meaning you don’t need to clutter your controller with any validation code. If your request is valid the message will be created, if it is not valid you’ll be redirected to the previous page and the errors will be flashed to the session. If the request was an AJAX request, a response containing the validation errors with a status code of 422 will be returned.

Authorization

The first method, authorize, in the MessageRequest.php file created can be used for authorizing the request. This method allows you to reject a request based on it’s source/initiator (authenticated user). You are expected to return a boolean. If true is returned, the code will carry on. But if false is returned a 403 http status code will be returned and your controller code won’t be executed.

Simply return true if you plan not to use your form request for authorization. I have done most of my authorization using middlewares. If you think you have a use for this method, go ahead. For example, in our application, we can check ownership of the message before allowing a user to update it, in another application it can be used to check if a user has enough credit to purchase a product.

Customize Error Message

If you choose to, you can also customize the error message flashed to the session when the validation fails in form requests. We can do this by overriding the messages method of the FormRequest object our MessageRequest class is extending. The method should return an array containing attributes and rule pairs, plus the error message that matches it.

Let’s customize the error message for the email and subject attributes.

//MessageRequest.phppublic function messages(){return [    'email.required' => 'Please provide an email were we can reach you.',    'subject.required'  => 'Subject cannot be empty. Trytell us in less than 100 characters what this is about.'];}

Request Path Based Validation

I utilize this method when I want to use the same form request class to validate more than one action on my model. For example, in our message application, we are validating the update request too. If you choose too, you can create another form request to handle this. But there is another way. What i do is define different rules in my form request class and choose the one to use based on the incoming request path. You need to adjust things a little bit to make this work.

In our MessagesController, type-hint MessageRequest class in the update method and cut the validation rules. Updated code should be:

//MessagesController.phppublic function update(MessageRequest $request, $id){    Message::find($id)->update($request->validated());    return redirect()->route('message.index');}

Create two new methods in MessageRequest.php

//MessageRequest.phppublic function createRules(){return [    'email' => 'required|email|max:50',    'category' => 'required',    'subject' => 'required|max:100',    'message' => 'required|max:500']}
public function updateRules(){return [ 'email' => 'required|email|max:50', 'subject' => 'required|max:100', 'message' => 'required|max:500']}

Finally, adjust the rules method to this:

//MessageRequest.phppublic function rules(){if( $this->is('message/create') ) {    return $this->createRules();} elseif ( $this->is('message/update/*') ) {    return $this->updateRules();}}

The is method allows you to verify that the incoming request path matches the given pattern. So we can use our MessageRequest class in two different methods(create and update) and once the request path matches the pattern given, the corresponding rule is used to validate it.

Request Method Based Validation

We are not left with only the option of using the route path to determine the validation rules to use, the route method can also be used to choose the validation rules to use. This works by verifying that the HTTP verb matches a supplied string. So whichever string matches our request method will determine the validation rules used.

//MessageRequest.phppublic function rules(){if( $this->isMethod('post') ) {    return $this->createRules();} elseif ( $this->isMethod('put') ) {    return $this->updateRules();}}

Finally:

There other parameters that you can specify if you find yourself needing to:

$redirect: the URI to redirect to if validation fails
$redirectRoute: the route to redirect to if validation fails
$redirectAction: the controller action to redirect to if validation fails

I think form requests provides a convenient way to simplify validation and help tidy up controllers. Hopefully, you’ll find good use for them as i have.

Thanks for reading.

--

--