Good content takes time and effort to come up with.

Please consider supporting us by just disabling your AD BLOCKER and reloading this page again.







Make Laravel Controllers Slim By Skimming Form Validation Request


SLIM CONTROLLERS LARAVEL VALIDATION PHP VALIDATION LARAVEL
05th May 2020 6 mins read
Share Article     Share On WhatsApp   Buy Me Coffee | StackCoder Buy Coffee


Bonjour Les Amis! In this tutorial I will explain you how to separate form validation from controllers and keep in requests class, So that your controllers are slim and you don't clutter too much of things in your controller.


Prerequisites


Working Laravel project or freshly installed Laravel project.


To create fresh Laravel project use the following command:


composer create-project --prefer-dist laravel/laravel project_name

For the sake of demonstration I will be showing User Registration Page. The form fields may not be exactly same as that I have. But this should give you heads up of how to do it.


Normal Class Validation


Usually you do the following ancient way to validate your form in your class.


INITIAL CODE


Here I am taking as INITIAL CODE so that you can compare with FINAL CODE that we will have in the end of this article. You will be really amazed with it.


public static function store()
{
    /** Normal Form Validation */
    request()->validate([
        'name'              => 'required|regex:/^[\pL\s\-]+$/u',
        'gender'            => 'required|in:male,female,other',
        'date_of_birth'     => 'required|date_format:Y-m-d',
        'country'           => 'required|exists:countries,id',
        'state'             => 'required|exists:states,id',
        'city'              => 'required|exists:cities,id',
        'email'             => 'required|email|unique:users,email',
        'phone'             => 'required|digits:10|starts_with:6,7,8,9|unique:users,phone',
        'password'          => 'required',
        'confirm_password'  => 'required|same:password'
    ]);


    try{
        /** Create User Code. I usually put it in Model class. 
            You can directly pass the form request for create, 
            but I am more of no no person for that 
        */
        $user = User::create([
            'name'          => request('name'),
            'gender'        => request('gender'),
            'date_of_birth' => request('date_of_birth'),
            'country_id'    => request('country'),
            'state_id'      => request('state'),
            'city_id'       => request('city'),
            'email'         => request('email'),
            'phone'         => request('phone'),
            'password'      => self::encrypt(request('password')),
        ]);
        if(!$user){
            throw new Exception('Oops! Some error while creating user. Try again.');
        }
        session()->flash('success', 'User Registered Successfully');
        return redirect('/auth/login');
    } catch(\Exception $e) {
        session()->flash('error', $e->getMessage());
        return redirect()->back()->withInput();
    }
}


As you can see in the above example we have form validation & user data adding to database and other code. The controller is cluttered with shit load of code.


Let's Refactor It (Form Requests To Rescue)


Laravel has a feature to move the form requests to separate request class.


Create a CreateUserRequest Class, where we can put all this hell lot of validation code. Use the following artisan command to create the form request in Laravel.


php artisan make:request CreateUserRequest


This creates the CreateUserRequest.php class in app/Http/Requests folder as shown in the following image


CreateUserRequest Form Request Class

CreateUserRequest Form Request Class


Now lets take the user registration form validation from UserController and add the validation in CreateUserRequest class rules() method as follows


class CreateUserRequest extends FormRequest
{
    public function authorize()
    {
        /** Make sure to make this true */
        return true;
    }

    public function rules()
    {
        /** Following is the same validation that you had written in your controller */
        return [
            'name'              => 'required|regex:/^[\pL\s\-]+$/u',
            'gender'            => 'required|in:male,female,other',
            'date_of_birth'     => 'required|date_format:Y-m-d',
            'country'           => 'required|exists:countries,id',
            'state'             => 'required|exists:states,id',
            'city'              => 'required|exists:cities,id',
            'email'             => 'required|email|unique:users,email',
            'phone'             => 'required|digits:10|starts_with:6,7,8,9|unique:users,phone',
            'password'          => 'required',
            'confirm_password'  => 'required|same:password',
        ];
    }

    /** You can customise validation messages here */
    public function messages()
    {
        return [
            'phone.required'    => 'Contact number is required',
            'phone.digits'      => 'Contact number must be numbers',
            'phone.starts_with' => 'Contact number is not valid'
        ];
    }
}


Don't forget to make authorize() function return true. If you want you can even make auth() validation and return true if the user has permission or not


public function authorize()
{
    /** You can check if the user can perform this 
        validation request based on his access. 

        For the sake of simplicity I am returning true here
    */
    /** Make sure to make this true */
    return true;
}


You can customise your validation messages in messages() function as shown below


public function messages()
{
    return [
        'phone.required'    => 'Contact number is required',
        'phone.digits'      => 'Contact number must be numbers',
        'phone.starts_with' => 'Contact number is not valid'
    ];
}

How Do We Use This In Controller


The above CreateUserRequest won't get called automatically we need to inject in UserController store method parameter as follows


use App\Http\Requests\CreateUserRequest;

public function store(CreateUserRequest $request)
{
    /** User Registration Code */
}


Now overall your UserController will look like the following:


use App\Http\Requests\CreateUserRequest;

public static function store(CreateUserRequest $request)
{
    try{
        /** Create User Code. I usually put it in Model class. 
            You can directly pass the form request for create, 
            but I am more of no no person for that 
        */
        $user = User::create([
            'name'          => request('name'),
            'gender'        => request('gender'),
            'date_of_birth' => request('date_of_birth'),
            'country_id'    => request('country'),
            'state_id'      => request('state'),
            'city_id'       => request('city'),
            'email'         => request('email'),
            'phone'         => request('phone'),
            'password'      => self::encrypt(request('password')),
        ]);
        if(!$user){
            throw new Exception('Oops! Some error while creating user. Try again.');
        }
        session()->flash('success', 'User Registered Successfully');
        return redirect('/auth/login');
    } catch(\Exception $e) {
        session()->flash('error', $e->getMessage());
        return redirect()->back()->withInput();
    }
}


This is much cleaner. Isn't it?


Move Business Logic To Model


This is lot of controversial topic ie where to put your business logic. As Taylore Otwell himself said we can put it in Models I usually do it there.


Even we can use the Repository Pattern and segregate lot of code moving to that folder. But in this article lets not argue on that. Let me write another article on the same.


Coming back to our code, once I move the registration code to User Model it will look some what this way


FINAL CODE


Which I am very much satisfied with


use App\Http\Requests\CreateUserRequest;

public static function store(CreateUserRequest $request)
{
    try{
        $user = User::register($request->all());
        if(!$user){
            throw new Exception('Oops! Some error while creating user. Try again.');
        }
        session()->flash('success', 'User Registered Successfully');
        return redirect('/auth/login');
    } catch(\Exception $e) {
        session()->flash('error', $e->getMessage());
        return redirect()->back()->withInput();
    }
}

Conclusion


There is lot of stuff to share with you guys. But as we know everything cant be covered in a single stretch. So stay tuned & keep learning. Don't forget to share with your friends.


WHATS NEXT?


You might be interested in reading few of my other articles


Route Model Binding In Laravel & Change Default Column id To Another Column

How To Run Raw Queries Securely In Laravel

Laravel 7.x Multiple Database Connections, Migrations, Relationships & Querying

How To Install Apache Web Server On Ubuntu 20.04 / Linux & Manage It

How To Create / Save / Download PDF From Blade Template In PHP Laravel

How To Add Free SSL Certificate In cPanel With ZeroSSL & Certbot

How To Securely SSH Your Server & Push Files With FileZilla

How To Push Files To CPanel / Remote Server using FTP Software FileZilla

How To Install Linux, Apache, MYSQL, PHP (LAMP Stack) on Ubuntu

How To Cache Static Files With NGINX Server

Redirect www to a non-www website or vice versa

How To Create Free SSL Certificate With Lets Encrypt/Certbot In Linux (Single / Multiple Domains)

How To Install Linux, NGINX, MYSQL, PHP (LEMP Stack) on Ubuntu

PHP Built-In Web Server & Testing Your Development Project In Mobile Without Any Software

How To Do Google reCAPTCHA Integration In PHP Laravel Forms


Happy Coding :)








Author Image
AUTHOR

Channaveer Hakari

I am a full-stack developer working at WifiDabba India Pvt Ltd. I started this blog so that I can share my knowledge and enhance my skills with constant learning.

Never stop learning. If you stop learning, you stop growing