Creating Custom Validation in Laravel

Creating Custom Validation in Laravel

Creating your validation

·

4 min read

Hello friends, how are you? hope you are always healthy. And stay motivated in the learning process.

This time I want to write about how to make custom validation in laravel. The scenario, I want to validate the email input whether the email is registered or not. To check the email, we need the help of a third party, https://www.validator.pizza/ . Pizza Validator is an api to check if a domain, or email is registered.

Next we also need the guzzlhttp package, http client to make requests.

Let's just install:

composer require guzzlehttp/guzzle

Then, run the command create a validation rule:

php artisan make:rule MailValidation

Then a file will be created in the app\Rules\MailValidation.php directory:

<?php

namespace App\Rules;

use Illuminate\Contracts\Validation\Rule;

class MailValidation implements Rule
{
    /**
     * Determine if the validation rule passes.
     *
     * @param  string  $attribute
     * @param  mixed  $value
     * @return bool
     */
    public function passes($attribute, $value)
    {

    }

    /**
     * Get the validation error message.
     *
     * @return string
     */
    public function message()
    {
        return 'The :attribute must be required.';
    }
}

By default the validator file has two methods. The passes method functions as a recipient of the value of user input, this method contains logic to determine whether the value of the input is passed or failed. This method has a boolean return value of true or false. If the status is true, the data will be passed and allowed for further processing. Meanwhile, if false, the validator will execute the message method. The message method is a method that returns a message if passes returns false.

Next in the MailValidation.php file, add a new method as a wrapper for the api request process to the pizza validator.

/**
 * wrapper/pembungkus request ke validator.pizza
 *
 * @return bool
 */
public function validateMail($email)
{
    $req = (new Client()) >get('https://www.validator.pizza/email/'. $email);
            $body = json_decode($req->getBody()->getContents());
            switch ($body) {
                case $body->status == 400:
                    return false;
                case !$body->mx:
                    return false;
                case $body->disposable:
                    return false;
                default:
                    return true;
            }
}

The above method will make a request, then it will return a response.

Furthermore, because the pizza validator limits requests to only 120 requests in an hour, the rest we will consider the email valid. For that we will create a new method again which functions to counter the number of requests, we will only store the counter data in the cache.

/**
 * Get the validation error message.
 *
 * @return string
 */
public function limitRequest()
{
    $range = Carbon::now()->addMinutes(60);
    Cache::put('remaining_requests', 
                Cache::increment('remaining_requests', 1), 
                $range);  

    return Cache::get('remaining_requests');  
}

Don't forget to call the Carbon package, and Cache at the top:

namespace App\Rules;

use Illuminate\Contracts\Validation\Rule;
use GuzzleHttp\Client;
use GuzzleHttp\Exception\ClientException;
use GuzzleHttp\Psr7\Request as GuzzleHttpRequest;
use Illuminate\Support\Facades\Cache;
use Carbon\Carbon;

If so, complete the method passes as follows:

public function passes($attribute, $value)
  {
      if ( ! filter_var($value, FILTER_VALIDATE_EMAIL)) {
          return false;
      }

      if ($this->limitRequest() >= 120) {
          return true;
      }

      if (ValidateMail() !== true) {
          return false;
      }

      return true;
  }

The above method will check whether the request is equal to, or greater than 120, if it does not need to make a request to the email validator, it will immediately be considered true.

<?php

namespace App\Rules;

use Illuminate\Contracts\Validation\Rule;
use GuzzleHttp\Client;
use GuzzleHttp\Exception\ClientException;
use GuzzleHttp\Psr7\Request as GuzzleHttpRequest;
use Illuminate\Support\Facades\Cache;
use Carbon\Carbon;

class MailValidation implements Rule
{
    /**
     * Determine if the validation rule passes.
     *
     * @param  string  $attribute
     * @param  mixed  $value
     * @return bool
     */
    public function passes($attribute, $value)
    {
        if ( ! filter_var($value, FILTER_VALIDATE_EMAIL)) {
            return false;
        }

        if ($this->limitRequest() >= 120) {
            return true;
        }

        if (ValidateMail() !== true) {
            return false;
        }

        return true;
    }

    /**
     * Get the validation error message.
     *
     * @return string
     */
    public function message()
    {
        return 'The :attribute tidak valid';
    }

/**
 * wrapper/pembungkus request ke validator.pizza
 *
 * @return bool
 */
public function validateMail($email)
{
    $req = (new Client()) >get('https://www.validator.pizza/email/'. $email);
    $body = json_decode($req->getBody()->getContents());
            switch ($body) {
                case $body->status == 400:
                    return false;
                case !$body->mx:
                    return false;
                case $body->disposable:
                    return false;
                default:
                    return true;
            }
}

/**
 * Get the validation error message.
 *
 * @return string
 */
public function limitRequest()
{
    $range = Carbon::now()->addMinutes(60);
    Cache::put('remaining_requests', 
                Cache::increment('remaining_requests', 1), 
                $range);  

    return Cache::get('remaining_requests');  
}

}

OK, the MailValidation.php script has been completed. now we will use the validation rule. The way we can extend it to the laravel validator, via AppServiceProvider.php in the boot() method, as follows:

public function boot()
   {
     Validator::extend('is_mail', 'MailValidation@passes');
   }

Then in the controller use the rule that we just created by:

$request->validate([
    'email' => 'required|string|is_mail',
]);

Or it could be in the usual way like this:

App\Rules\MailValidation

$request->validate([
    'email' => ['required', 'string', new MailValidation()],
]);

Okay, that's all for this article, I hope it's useful. Wait for other posts about Laravel here.