Handle form data smartly with FormRequest class of Laravel

Image for post
Image for post

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');
}

rules()

/**
* 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.

messages()

/**
* @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.

attributes()

// 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’.

merge($input)

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
]
*/

prepareForValidation()

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.

all()

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;
}

failedAuthorization()

“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.

Written by

A software engineer from Bangladesh.

Get the Medium app

A button that says 'Download on the App Store', and if clicked it will lead you to the iOS App store
A button that says 'Get it on, Google Play', and if clicked it will lead you to the Google Play store