bugarinov/chain-validation

Classes which implements the Chain of Responsibility pattern in validating data. Intended primary use is for handling complex validations.

v0.2.1 2022-07-21 12:14 UTC

This package is auto-updated.

Last update: 2024-03-30 10:33:24 UTC


README

Notice:

The latest build is 0.2.x and is not backwards compatible with 0.1.x versions. See Migration for details.
Alternatively, you can read 0.1.x-README.md for versions 0.1.x.


Chain Validation is a simple PHP library for handling very complex validations that goes beyond checking of data types, format and values of a given data. It uses the Chain of Responsibility design pattern in order to execute each validation in a consecutive manner. The execution will stop once an error occured during the validation process within a link. You can alter the data as it goes through the chain, depending on your requirements.


Usage

Defining and executing validations

Usage is simple. First, group your validations by purpose/relevance and create a new class for each validation group which extends the AbstractLink class.

class ValidationOne extends AbstractLink
{
    public function evaluate(?array $data): EvaluationResult
    {
        /*
        * Run your validation process here which will
        * set the value of $validationFailed whether
        * the validation failed (true) or not (false)
        */
        if ($validationFailed) {
            return new ResultFailed('your error message here', 400);
        }

        /*
        * If the validation did not fail, return an
        * evaluation result which contains the data
        */
        return new ResultSuccess($data);
    }
}

You can run the validations using the ChainValidation class. The chain process each validation in exact order or in First in, First out manner.

$chain = new ChainValidation();

$chain->add(new ValidationOne());
$chain->add(new ValidationTwo());
$chain->add(new ValidationThree());
$chain->add(new ValidationFour());

$validatedData = $chain->execute($data);

Catching errors

To know whether an error occured or not, you can use the hasError() function of the ChainValidation class and get the error message using the getErrorMessage() function after the validation execution. You can get the corresponding error code using the getErrorCode() function.

$validatedData = $chain->execute($data);

if ($chain->hasError()) {
    throw new Exception($chain->getErrorMessage());
    /*
    * or your preferred way of handling errors e.g. returing a response,
    * throwing an HttpException (if you are using Slim or any similar framework), etc..
    */
}

// Some processes here if the validation succeeds e.g. committing of data to the database
commitToDatabase($validatedData);

If the chain validation succeeds, it will return the validated data, otherwise it will return null.


Migration from 0.1.x to 0.2.x

In order to migrate from 0.1.x to 0.2.x, you just need to replace the execute function on each link with the evaluate function.

From v0.1.x

class ValidationOne extends AbstractLink
{
    public function execute(?array $data): ?array
    {
        if ($validationFailed) {
            return $this->throwError('your error message here', 400);
        }

        return $this->executeNext($data);
    }
}

to v0.2.x

class ValidationOne extends AbstractLink
{
    public function evaluate(?array $data): EvaluationResult
    {
        if ($validationFailed) {
            return new ResultFailed('your error message here', 400);
        }

        return new ResultSuccess($data);
    }
}

Tests

Run the tests using composer test.

Tests with mocking of Link's evaluate function are added.