Creating Custom Form Request Validation in Laravel Projects

This tutorial describes how to create and use Custom Form Request Validation in your Laravel (5.8 or 6) projects.
Provided by Leumas Naypoka / www.apphp.com

There is few ways to validate form submission data in Laravel.

The standard way is to use Validator facade in the beginning of your controller. Lets see the example:

<?php
/**
 * Store a newly created resource in storage.
 *
 * @param \Illuminate\Http\Request $request
 *
 * @return \Illuminate\Http\Response
 */
public function store(Request $request)
{
    
$validator Validator::make($request->all(), [
        
"title"  => "required|min:5|max:200",
        
"body_content"=> "required|min:10",
        
"blog_tag_id" => "nullable",
    ],[
        
"title.required" => "Please write a title",
        
"title.min" => "The title has to have at least :min characters.",
        
"title.max" => "The title has to have no more than :max characters.",
        
"body_content.required" => "Please write some content",
        
"body_content.min" => "The content has to have at least :min characters",
    ]);

    
// ... next part of code after validation

?>


In this example we perform validation inside the controller's action. It looks nice enough until you want to use the same code in another places: when you create a post in Backend or if you want to add a Unit tests. In such cases, you will copy-paste the same pieces of your code, that is not good, because you have to support all of them and such style of programming breaks DRY principle (Don't Repeat Yourself).

So... what the better way to implement such validation? Laravel allows us to create our own Request class, instead of using a standard \Illuminate\Http\Request and use as a function parameter.

The first thing you have to do it to create such class.
Run following command:

$ php artisan make:request App\Http\Requests\MyOwnRequest



This command will create MyOwnRequest request class in App\Http\Requests\ directory.
By default it will be looked as follow:

<?php
namespace App\Http\Requests\Auth;

use 
Illuminate\Foundation\Http\FormRequest;

class 
MyOwnRequest extends FormRequest
{
    
/**
     * Determine if the user is authorized to make this request.
     *
     * @return bool
     */
    
public function authorize()
    {
        return 
false;
    }

    
/**
     * Get the validation rules that apply to the request.
     *
     * @return array
     */
    
public function rules()
    {
        return [
            
//
        
];
    }
}
?>


Now you can move there your validation rules and replace Request parameter in store() method with MyOwnRequest:

Your controller store() method will be looking:

<?php
/**
 * Store a newly created resource in storage.
 *
 * @param \Illuminate\Http\MyOwnRequest $request
 *
 * @return \Illuminate\Http\Response
 */
public function store(MyOwnRequest $request)
{
 
    
// ... next part of code after validation
}
?>


MyOwnRequest class will be looking:
Remember to turn return value of authorize() method to TRUE!

<?php
namespace App\Http\Requests\Auth;

use 
Illuminate\Foundation\Http\FormRequest;

class 
MyOwnRequest extends FormRequest
{
    
/**
     * Determine if the user is authorized to make this request.
     *
     * @return bool
     */
    
public function authorize()
    {
        return 
true;
    }

    
/**
     * Get the validation rules that apply to the request.
     *
     * @return array
     */
    
public function rules()
    {
        return [
           
"title"  => "required|min:5|max:200",
           
"body_content"=> "required|min:10",
           
"blog_tag_id" => "nullable",
        ];
    }
}
?>


Looks much better, right? But what if you want to specify custom validate messages? It's easy to implement with messages() method of your validator class. You simply have to define an array, where the key is a field name and the value is the custom message you want to show.

Let's see how to do this:

<?php
namespace App\Http\Requests\Auth;

use 
Illuminate\Foundation\Http\FormRequest;

class 
MyOwnRequest extends FormRequest
{
    
/**
     * Determine if the user is authorized to make this request.
     *
     * @return bool
     */
    
public function authorize()
    {
        return 
true;
    }

    
/**
     * Get the validation rules that apply to the request.
     *
     * @return array
     */
    
public function rules()
    {
        return [
            
"title"  => "required|min:5|max:200",
            
"body_content"=> "required|min:10",
            
"blog_tag_id" => "nullable",
        ];
    }

    
/**
     * Custom message for validation
     *
     * @return array
     */
    
public function messages()
    {
        return [
            
"title.required" => "Please write a title",
            
"title.min" => "The title has to have at least :min characters.",
            
"title.max" => "The title has to have no more than :max characters.",
            
"body_content.required" => "Please write some content",
            
"body_content.min" => "The content has to have at least :min characters",
        ];
    }
}

?>


Ok, good. But what to do if you need to validate a set of fields, lets say: few checkboxes or few file fields? In this case you may use asterisk * to prepare validation rules. Check below how we define validation rules for set of fields. I hope it's clear and understandably enough.

<?php
public function rules(): array
{
   return [
      
"files.*" => "required|image|mimes:jpg,jpeg,png",
      
"attrs.*.from" => "nullable|numeric",
      
"attrs.*.to" => "nullable|numeric",
   ];
}
?>


Laravel creates validation messages automatically, so sometimes you will need to provide a special names to your fields. You may use the following language lines are used to swap attribute place-holders with something more reader friendly such as E-Mail Address instead of "email" or indexes in array. This simply helps us make messages a little cleaner.

<?php
public function attributes(): array
{
   return [
      
"receivers" => "Nice name",
      
"subject" => "Like name",
      
"body" => "Another Name",
      
"notify.blog.*" => "Blog Notification value",
   ];
}
?>


If you want to perform your own validation, you may use withValidator() method. It's useful when you need to perform additional or very complicated validation, after the main validation was passed (or not). In example below we check if an email presents in a list of pre-approved emails. Take in account, that there are some methods you may use:
$validator->after()
$validator->fails()
etc.

<?php
/**
* @param  \Illuminate\Validation\Validator  $validator
* @return void
*/
public function withValidator(Validator $validator)
{
   
$email $validator->getData()['email'] ?? '';
   
$validator->after(
      function (
$validator) use ($email) {
         if (
is_null(\DB::table('pre_approved')->where('email',$email)->first())) {
            
$validator->errors()->add(
               
'email'
               
'This email does not exist on our pre-approved email list'
            
);
         }
      }
   );                            
}
?>


As mentioned before, the form request class also contains an authorize method. You may check if the authenticated user actually has the authority to change a given resource. Lets see an example when user actually owns a blog comment and attempt to update it:

<?php
/**
 * Check if the user is authorized to make this request.
 * @return bool
 */
public function authorize()
{
   
$comment Comment::find($this->route('comment'));
   return 
$comment && $this->user()->can('update'$comment);
}
?>


And the last thing, if you want to redefine a route if validation fails, you may do that by redefining $redirectRoute property:

<?php
// The named route to redirect to if validation fails.
protected $redirectRoute 'home';
?>


Comments


Please post only comments related to the original tutorial. Be polite and helpful, do not spam or offend others.
Create Your Free Account
Please remember that this information is essential to use our services correctly.
After creating the account you will be able to download all of our FREE products.
Fields marked with * are mandatory






Please send me information about updates, new products, specials and discounts from ApPHP!
We recommend that your password should be at least 6 characters long and should be different from your username/email. Please use only letters of the English alphabet to enter your name.

Your e-mail address must be valid. We use e-mail for communication purposes (order notifications, etc). Therefore, it is essential to provide a valid e-mail address to be able to use our services correctly.

All your private data is confidential. We will never sell, exchange or market it in any way. Please refer to Privacy Policy.

By clicking "Create Account", you are indicating that you have read and agree to the ApPHP Terms & Conditions.

Quick Registration with: Facebook / Google