Refactoring Validation to Form Requests

Validation is vital yet tricky part of every application. Preparing for possibilities, filtering the incoming data, sanitizing them before saving, checking for conditions and much more. Laravel offers a helpful and fluent way to validating data from requests via the form requests.

 

Generating form requests

Laravel’s artisan CLI makes it easy to generate form requests. By running the artisan make:request we get our form request class, in the app/Http/Requests directory. This class contains an authorize() and a rules() method. In the authorize method we can determine if the current user is allowed to make the current request. In the rules method we return an array of validation rules, which is not contained in our controller anymore, but in this dedicated class.

Using them in our controllers

In a standard CRUD application, the actions where we want to validate or authorize are the store, update and delete operations. Our update rules a bit different than the rules we use when storing a new record. It’s also possible we allow to delete records only for the specified users. Because of these use cases, it’s a good practice to make three different requests for the three different actions.

By Laravel’s brilliant dependency injection, all we have to do, to type-hint our requests in our controller methods, and the rest is done by the framework itself. There is no need to use the validation facade or create a validation method in our controller. Laravel checks the incoming request, pass it to the type-hinted form request and does the validation and authorization automatically.

Real life example

Let’s say we have a blog, where we are woking with posts. We have a PostsController, and also we generated three requests for the specific actions.

// app/Http/Controller/PostsController.php

<?php

namespace App\Http\Controller;

use App\Post;
use App\Http\Requests\{StoreRequest, UpdateRequest, DestroyRequest};

class PostsController extends Controller
{
    /**
     * Store a newly created resource in storage.
     *
     * @param  \App\Http\Requests\StoreRequest  $request
     * @return \Illuminate\Http\Response
     */
    public function store(StoreRequest $request)
    {
        //
    }

    /**
     * Update the specified resource in storage.
     *
     * @param  \App\Http\Requests\UpdateRequest  $request
     * @param  \App\Post  $post
     * @return \Illuminate\Http\Response
     */
    public function update(UpdateRequest $request, Post $post)
    {
        //
    }

    /**
     * Remove the specified resource from storage.
     *
     * @param  \App\Http\Requests\DestroyRequest  $request
     * @param  \App\Post  $post
     * @return \Illuminate\Http\Response
     */
    public function destroy(DestroyRequest $request, Post $post)
    {
        //
    }
}

We give the requests as the first parameter of our methods. The rest is Laravel’s job to do. The requests are called before any logic in the controller is triggered. That means if there is any error, the controller action is intercepted by the form requests.

Take a look at the UpdateRequest to see how validation and authorization work.

// app/Http/Requests/UpdateRequest.php

<?php

namespace App\Http\Requests;

use Illuminate\Validation\Rule;
use Illuminate\Foundation\Http\FormRequest;

class UpdateRequest extends FormRequest
{
    /**
     * Determine if the user is authorized to make this request.
     *
     * @return bool
     */
    public function authorize()
    {
        return $this->user()->can('update', $this->route('post'));
    }

    /**
     * Get the validation rules that apply to the request.
     *
     * @return array
     */
    public function rules()
    {
        return [
            'title' => 'required',
            'slug' => [
                'required',
                Rule::unique('posts')->ignore($this->route('post')->id),
            ],
        ];
    }
}

It’s a huge advantage we can use Policies in our form requests. In this particular case, we check if the user is allowed to update the posts trough a Policy class. If the user is authorized to make this request, the validation is triggered. Otherwise, it returns with an unauthorized response.

In the rules method, we specify the rules we want to apply on the incoming data. To make the rules more readable, Laravel offers the Rule class. With this helper, we can generate rules painlessly.

If there is an error during the validation, the framework fills up the error bag. From our blade files, we can have access to the with the $errors variable. If we use an API what returns a JSON response, the errors are being converted to JSON automatically. It’s a nice way to use them from a JS library like Vue.

Summary

Form requests are another neat tool what Laravel provides. Validation and authorization are critical and fundamental. It’s good to have a dedicated place to work with them.

If you want to read more about Laravel’s form requests, check out the documentation.

Special thanks for the following recource(s): Icon made by Pixel perfect from www.flaticon.com

Leave a Reply

Your email address will not be published. Required fields are marked *