Overview

Description

Caldera Validation is a validation layer for user-generated data.

As with the other Caldera components it has been built to be swappable and modular.

Installation

The easisest way to install it is to use Composer:

composer require vecode/caldera-validation

Requires

  • php: >=8.1
  • ext-mbstring: *

Basic usage

Getting started

The way Caldera Validation works is through conditions, you set them and then pass a data package to get validated against that set of conditions.

So, first you will need to create a Validation instance:

use Caldera\Validation\Validation;

$validation = new Validation();

Then you can start to add conditions:

$validation->condition('name', 'required')
    ->condition('email', ['required', 'email'])
    ->condition('first_name', 'required')
    ->condition('last_name', 'required')
    ->condition('password', 'required')
    ->condition('password_confirm', ['required', 'same:password']);

A condition has the name of a field and the rules for that field (if it is required, if it must be an email, etc.).

The field names will be used to check the ones present in the data package, so make sure to use the same ones in your forms.

To validate the data, pass it to the validate method:

$fields = $request->getParsedBody();
$validation->validate($fields);

If the validation fails, a ValidationException will be thrown so it's a good idea to wrap the call in a try...catch block:

use ValidationException;

$fields = $request->getParsedBody();

try {
    $validation->validate($fields);
} catch (ValidationException $e) {
    var_dump( $e->getErrors() );
    exit;
}

The ValidationException class has a getErrors method to get all the validation errors, so that you can display or log them.

Rule types

The following are the available rule types:

  • required - Validate a required field
  • alpha - Validate an alphabetic-only field
  • alphanum - Validate an alpha-numeric field
  • num - Validate a numeric-only field
  • slug - Validate an slug field
  • regex - Validate a field using a regular expression, additional parameter <regular_expresion>
  • email - Validate an email field
  • same - Validate a same-to-another field, additional parameter <field_name>
  • different - Validate a different-to-another field, additional parameter <field_name>
  • after - Validate a field with a date after the one specified, additional parameter <date(YYYY-MM-DD)>
  • before - Validate a field with a date before the one specified, additional parameter <date(YYYY-MM-DD)>
  • between - Validate a field with a number or length between the given range, additional parameter <min,max>
  • min - Validate a field with a number or length that is at least the given one, additional parameter <number>
  • max - Validate a field with a number or length that is at most the given one, additional parameter <number>
  • size - Validate a field with a number or length that is exactly the given one, additional parameter <number>
  • array - Validate that a field is an array
  • numeric - Validate that a field is numeric
  • string - Validate that a field is a string

Some rule types require an additional parameter:

# 'key' must be a 32 character hash
$validation->condition('key', 'regex:/[a-z0-9]{32}/i');

# 'confirm' must the the same as 'password'
$validation->condition('confirm', 'same:password');

# 'alias' must the the same as 'name'
$validation->condition('alias', 'different:name');

# 'date_of_birth' must be after '1986-03-26'
$validation->condition('date_of_birth', 'after:1986-03-26');

# 'date_of_birth' must be before '1986-03-26'
$validation->condition('date_of_birth', 'before:1986-03-26');

# 'quantity' must be between 5 and 10
$validation->condition('quantity', 'between:5,10');

# 'quantity' must be at minimum 3
$validation->condition('quantity', 'min:3');

# 'quantity' must be at maximum 5
$validation->condition('quantity', 'max:5');

# 'length' must be of size 3
$validation->condition('length', 'size:3');

Just add the value of the parameter after a colon ':'.

Custom rules

Custom validators can also be specified, either by passing a Closure:

$validation->condition('url', function(array $fields, string $key, array $options, Closure $fail) {
    $value = $fields[$key] ?? '';
    $valid = $value && filter_var($value, FILTER_VALIDATE_URL);
    if ( !$valid ) {
        $fail('Invalid URL specified');
    }
});

Or by passing the FQN of a class that implements RuleInterface:

use App\Validation\UrlRule;

$validation->condition('url', UrlRule::class);

UrlRule being defined as:

use Caldera\Validation\RuleInterface;

class UrlRule implements RuleInterface {

    /**
     * Invoke rule
     * @param  array   $fields  Fields array
     * @param  string  $key     Field key
     * @param  array   $options Options array
     * @param  Closure $fail    Failure callback
     * @return void
     */
    public function __invoke(array $fields, string $key, array $options, Closure $fail): void {
        $value = $fields[$key] ?? '';
        $valid = $value && filter_var($value, FILTER_VALIDATE_URL);
        if ( !$valid ) {
            $fail('Invalid URL specified');
        }
    }
}

As you can see, RuleInterface is an invokable interface, and so you must implement the __invoke method.