Handle form data smartly with FormRequest class of Laravel

In my last article, I talked about how you can minimize your controller by putting the code out from it and put it somewhere else. And to do that I refactored the method length from 50+ line to 5–8 line. Rest of the code we put in a FormRequest class. And it worked perfectly.

Today we gonna discuss some methods of FormRequest class of Laravel which are really helpful if you know how to use them. To make a fresh new FormRequest class we need to fire the command below:

php artisan make:request YourRequest

This command will create a new YourRequest class under your app\Http\Requests directory with two methods in it. One is the authorize() method and the other is the rules() method. Let's have a quick overview of them.

authorize()

This method returns a boolean value. It returns true if the user is eligible for the request. By default, the method returns false. If you don’t need to check anything then just return true. Otherwise, you will get unauthorized errors all the time you use the FormRequest class. But this method is a very good place to check the user’s access and eligibility. If the criteria checks failed in this method(return false) the rest of the methods will not be called. So you can say this method an entry point for the class.

/**
* Determine if the user is authorized to make this request.
*
* @return bool
*/
public function authorize()
{
return false; // trough unauthorized error
return true; // no check, allowing to go further return auth()->check(); // returns true if user is logged in /* your custom logic to check user's role. If user has
the 'customer' role it will return true or false. */
return auth()->user()->hasRole('customer');
}

This is one of the default methods that take place when you hit the make:request command. This method returns an array. An array that holds the validation rules for your inputs. Here you can apply rules for your form data.

/**
* Get the validation rules that apply to the request.
*
* @
return array
*/
public function rules()
{
return [
'name' => 'required|max:100',
'email' => 'required|email|unique:users',
'password' => 'required|confirmed',
'contact_number' => 'required',
'shipping_address' => 'required',
'coupon' => 'nullable|exists:coupons,code',
'products.*.id' => 'required|exists:products,id',
'products.*.price' => 'required|numeric',
'products.*.quantity' => 'required|numeric'
];
}

By default, Laravel generates the above two methods when you create a FormRequest. But there is a lot of methods that ship with the core FormRequest class. As your created FormRequest class will extend the core FormRequest class by default, you can call them or override them anytime you want. Let’s see some awesome methods from them.

This method returns an array containing your custom messages for the errors. Whenever an error occurs built-in validation exceptions are thrown with some message to guide the users. But it always names the field according to the keys you applied for validation rules. This is awesome as the key is auto mapped. But sometimes you might not want to show messages as you named your key. You might show it differently or in a user-friendly way so that your users understand it. In this case, you can override the default error messages by writing a new one.

/**
* @return array|string[]
*/
public function messages()
{
return [
'product_id.required' => 'The product field is required',
'product_id.exists' => 'The product do not exist',

];
}

Here if you do not override the default error messages the user will see errors something like this:

The product id field is required

The product id do not exist

You might have named product_id for your coding purpose, but do the user know them? So to provide a nice, understandable message you should override them and the messages() method will help you with that. You can use localization on the messages too.

This method also returns an array. If you want to show any custom name for the attribute in the error message this gonna help you. This is kind of similar to the messages() method but rather than changing the whole new custom message you will just change the attribute name here.

// before using attributes method"errors": {
"product_id": [
"The product id field is required."
]
}
// after using attributes methodpublic function attributes()
{
return [
'product_id' => 'product',
];
}
"errors": {
"product_id": [
"The product field is required."
]
}

As you can see the attribute name in the error messages got replaced from ‘product_id’ to ‘product’.

This method takes an array as its parameter. As the name suggests, this method is used to merge your extra data with your actual request. This method can be called in your controller or anywhere when you want to merge something in the request. Let’s see an example:

dump($request->all());
/*
[
'name' => 'John Doe',
'email' => 'john@example.com'
]
*/

// merging is_active key with the request
$request->merge([
'is_active' => true
]);

dump($request->all());
/*
[
'name' => 'John Doe',
'email' => 'john@example.com',
'is_active => true
]
*/

This is a very useful method that allows you to modify or put some extra logic before applying validation rules. You can merge or filter any data from the request array here before the validation rules are applied.

protected function prepareForValidation()
{
$this->merge([
'date' => now()->toDateString(),
'user_id' => auth()->id()
]);
}

As you can see, we are merging the current date and logged user id to our request array so that we don’t need to manage them during database transactions.

Another way of modifying your request array is the all() method. Here in this method you can put/remove any key you want as like the prepareForValidation() method. The all() method returns an array with all the request key available. Use this method carefully as you may end up overriding the attributes shipped with your request. Let’s say your form data includes the name of the user. So you have the name key in your request array.

public function store(App\Http\Request\UserRequest $request)
{
echo $request->has('name'); // true
}
// and in the UserRequest class you overridden the all() method
public function all($keys = null)
{
return [
'foo' => 'bar'
];
}
// after overriding the all() method
public function store(App\Http\Request\UserRequest $request)
{
echo $request->has('name'); // false
echo $request->has('foo'); // true
}

To avoid this unwanted situation always fetch the actual request array by calling the parent all() method. Then you can modify/remove any key or do whatever you want to do with them. Then return the modified array.

public function all($keys = null)
{
// getting actual request array
$payload = parent::all();

// adding new value
$payload['foo'] = 'bar';

// returning the with the new value
return $payload;
}

This method is very useful while dealing with API or showing a custom message for authorization exception. While using the authorize() method of FormRequest class an error is thrown with status code 403 if the user is unauthorized. The message looks like this.

“The action is unauthorized”

You want to replace the text with a more friendly exception message to your users. In that case, you can use the failedAuthorization() method.

protected function failedAuthorization()
{
throw new AuthorizationException("Sorry you don't have access");
}

That’s it. All of the above methods are there to help you organize your code. All you need is to know them and use them where they fit.

Thanks for reading. Hit claps if you liked it.

A software engineer from Bangladesh.