Object Validator for PHP 8

Written by skillstacker | Published 2022/07/14
Tech Story Tags: php | webdev | programming | coding | php-development | opensource | debugging | guide

TLDRThis is simple attribute validation for PHP Models, based on the new features, presented in PHP 8. It works as a standalone and can be used in custom projects or in libraries like Symfony and Laravel.via the TL;DR App

Have you ever tried to validate an object in PHP. Maybe you use Models, ViewModels or RequestModels. Maybe you hate writing if-else, loops and swiches to check your values. Maybe you do not like to use different validators for every framework.

At least I do.

So I present to you my general solution using the strengths of PHP 8. Clean, concise, and easy.

What this does is use the new PHP attributes to validate your value objects. (Especially if you are using DDD) or/and you do not want this to depend on a specific framework.

It consists of the following features:

  • Lots of validations
  • Supports also nested object validation
  • Repeatable validation attributes
  • Works with private properties and methods
  • Works with constructor promotion
  • Memory and time profiling
  • Custom error messages
  • Custom property and method names for the exceptions
  • Severity levels
  • Debug explorer
  • Callback execution

Example

<?php

use RMValidator\Attributes\PropertyAttributes\Collection\UniqueAttribute;
use RMValidator\Attributes\PropertyAttributes\File\FileExtensionAttribute;
use RMValidator\Attributes\PropertyAttributes\File\FileSizeAttribute;
use RMValidator\Attributes\PropertyAttributes\Numbers\RangeAttribute;
use RMValidator\Attributes\PropertyAttributes\Object\NestedAttribute;
use RMValidator\Attributes\PropertyAttributes\Strings\StringContainsAttribute;
use RMValidator\Enums\ValidationOrderEnum;
use RMValidator\Options\OptionsModel;
use RMValidator\Validators\MasterValidator;

require __DIR__ . '/vendor/autoload.php';


class Test 
{
    public function __construct(
        #[RangeAttribute(from:10, to:50)]
        #[RangeAttribute(from:10, to:30)]
        public int $param)
    {

    }

    #[RangeAttribute(from:10, to:30)]
    const propTest = 40;

    #[UniqueAttribute()]
    public function custom() {
        return ['asd', 'asdk'];
    }

    #[FileSizeAttribute(fileSizeBiggest: 20, fileSizeLowest: 10)]
    #[FileExtensionAttribute(expected:['php'])]
    private function getFile() {
        return __FILE__;
    }

    #[FileSizeAttribute(fileSizeBiggest: 20, fileSizeLowest: 10)]
    #[FileExtensionAttribute(expected:['php'])]
    public string $file = __FILE__;

    #[StringContainsAttribute(needle:"asd")]
    public string $string = "23asd";

    #[RangeAttribute(from:10, to:30)]
    public int $prop = 40;
}

class UpperTest
{
    #[NestedAttribute(excludedProperties:['param'])]
    private Test $test;

    public function __construct(Test $test) {
        $this->test = $test;
    }
}

$test = new Test(40);

try {
    MasterValidator::validate(new UpperTest($test), 
    new OptionsModel(orderOfValidation: [ValidationOrderEnum::PROPERTIES, 
                                         ValidationOrderEnum::METHODS,
                                         ValidationOrderEnum::CONSTANTS], 
                     excludedMethods: ['getFile'], 
                     excludedProperties: ['file']));
} catch(Exception $e) {
    var_dump($e);
}

I am getting exited how this thing gets shape, but it still can be developed further and evolve. I will enjoy all sorts of feedback, recommendations and support. :)

It can be found in the link below.

https://github.com/IvanGrigorov/VMValidator

Also published here.


Written by skillstacker | Software developer - PHP and JS workaholic - http://ASP.NET and Angular Enthusiast πŸ‘¨β€πŸ’» 🌍 🏟️ βš½πŸƒβ€β™‚οΈπŸ€Έβ€β™‚οΈ β˜• πŸ”­ πŸŽ‡
Published by HackerNoon on 2022/07/14