Using Laravel's Illuminate Validation in any PHP project

geowrgetudor

George Tudor

Posted on February 19, 2022

Using Laravel's Illuminate Validation in any PHP project

I'm developing a Wordpress plugin that requires strict data for the frontend. The frontend is built with Vue.js and it's basically a multistep wizard where every step is represented by a specific Vue component.

A little bit of context

I want to give the freedom to any developer that's going to use this wizard to pass any step they want in any order they want. On the backend side, each step is represented by a class that's instantiated as follows:

new \StaxWp\Gandalf\Core\Components\YoutubeVideo(
    [
        'title'       => '',
        'description' => '',
        'url'         => '',
        'autoplay'    => false,
    ],
    1,
);
Enter fullscreen mode Exit fullscreen mode

This is a step that contains a title, a description, an url and an option to autoplay. Every step accepts in its constructor an array of data and an int for priority. Because we're humans and we can make mistakes I need to make sure all the fields from the array have specific values.

If you are familiar with Laravel, you know how the validation works. We can use the same validation outside Laravel. This is how I enforced validation rules for my step's data array:

final class YoutubeVideo extends Step {

    /**
     * YoutubeVideo constructor
     *
     * @param array   $data
     * @param integer $priority
     */
    public function __construct( array $data, int $priority = 0 ) {
        parent::__construct( $data, $priority );

        $this->add_validation_rules(
            [
                'title'       => 'sometimes|required|string|nullable',
                'description' => 'sometimes|required|string|nullable',
                'url'         => [ 'required', 'string', 'regex:/^(https?\:\/\/)?(www\.)?(youtube\.com|youtu\.be)\/watch\?v\=\w+$/' ],
                'autoplay'    => 'required|boolean',
            ]
        );
    }

}
Enter fullscreen mode Exit fullscreen mode

This of course won't work out of the box, so first we'll need to install illuminate/validation and illuminate/translation.

Setting up the requirements

composer require illuminate/validation
composer require illuminate/translation
Enter fullscreen mode Exit fullscreen mode

Next we need to include the following in our class...

use Illuminate\Container\Container;
use Illuminate\Filesystem\Filesystem;
use Illuminate\Translation\FileLoader;
use Illuminate\Translation\Translator;
use Illuminate\Validation\Factory;
Enter fullscreen mode Exit fullscreen mode

...then declare our private variable for validation and validation rules...

/**
* Step data validator
*
* @var Factory
*/
private $validation;

/**
* Step data validation rules
*
* @var array
*/
private $validation_rules = [];
Enter fullscreen mode Exit fullscreen mode

... and then we need instantiate our validator in the constructor:

$loader           = new FileLoader( new Filesystem(), 'lang' );
$translator       = new Translator( $loader, 'en' );
$this->validation = new Factory( $translator, new Container() );
Enter fullscreen mode Exit fullscreen mode

I'm not gonna add any localization files for the error messages because I won't display them. Everytime the validator fails I'm gonna throw an exception.

Actually doing the validation

Every step is casted to array and converted to JSON and then passed to the Vue, so where do I do the validation? In the array casting function of course:

/**
* Get step as array
*
* @return mixed
*/
public function to_array() {
    $this->validate_data();

    return get_object_vars( $this );
}

/**
* Validate step's data
*
* @return mixed
*/
protected function validate_data() {
    if ( ! empty( $this->data() ) && empty( $this->validation_rules ) ) {
        throw new Exception( $this->type() . ' has data but no validation rules.' );
    }

    $validator = $this->validation->make( $this->data(), $this->validation_rules );

    if ( $validator->fails() ) {
        throw new Exception( $this->type() . ' has an incorrect data format.' );
    }
}
Enter fullscreen mode Exit fullscreen mode

By doing this I know for sure that my $data array has all the required fields and each field has the required value.

I hope you've found this short tutorial useful.

Support & follow me

Buy me a coffee Twitter GitHub Linkedin
💖 💪 🙅 🚩
geowrgetudor
George Tudor

Posted on February 19, 2022

Join Our Newsletter. No Spam, Only the good stuff.

Sign up to receive the latest update from our blog.

Related