Skip to content

PropertyGate and Gate::assert()

Verja\PropertyGate validates a single scalar value through a filter → validate pipeline. It is used internally by Gate's typed methods, but can also be used directly and is the basis for Gate::assert().

Optional by default

Unlike Gate and ArrayGate, a PropertyGate has no required prefix validator by default. When used as a property inside a Gate, absent or empty values are skipped automatically by the parent gate. Pass 'required' explicitly to enforce presence:

$gate = new PropertyGate('required', 'strLen:3:20');

Using PropertyGate directly

use Verja\PropertyGate;

$gate = new PropertyGate('trim', 'notEmpty', 'strLen:3:100');
$result = $gate->validate($input);

if ($result->valid) {
    $value = $result->data; // trimmed, validated string
} else {
    foreach ($result->errors as $error) {
        echo $error->message . "\n";
    }
}

Filters and validators are passed in order — filters run first, validators after:

// Execution: trim → cast to int → between check
$gate = new PropertyGate('trim', 'integer', 'between:1:100');

The ! prefix negates a validator:

$gate = new PropertyGate('!notEmpty'); // value must be empty

Gates as type options

A PropertyGate can hold one or more gate arguments in addition to filters and validators. Gates are detected automatically when a GateInterface instance or a plain array is passed. They always run after all validators.

Single gate — delegate validation

Pass one gate to hand validation off entirely after the validators pass:

use Verja\Gate;
use Verja\PropertyGate;

// isStructured must pass first; then the nested Gate handles the properties
$gate = new PropertyGate('isStructured', (new Gate())->string('city', 'required'));

This is how ->object() works internally.

Multiple gates — implicit union (OR)

Pass two or more gates to require the value to satisfy at least one of them. The first gate that passes wins; its validated and filtered data is returned.

Arrays are converted to a PropertyGate automatically, so each array option is a compact shorthand for a set of validators:

// Value must be a string (min 3 chars) OR an array of exactly 2 strings
$gate = new PropertyGate(
    ['isString', 'strLen:3'],
    new ArrayGate('exactly:2', ['isString'])
);

This also works directly in typed Gate methods. Validators run first; then the gate options are tried:

// isString is validated first; then the value must match 'dateTime' OR 'date'
$gate->string('start', ['dateTime'], ['date']);

When all gates fail, the error key is NO_OPTION_MATCHED and per-option errors are collected under __or__.0, __or__.1, … in the error map.

Union gate nullable

To make a union-typed property optional, pass 'nullable' alongside the gates. The nullable prefix runs before the gates and short-circuits on null:

$gate->any('field', 'nullable', new PropertyGate('isString'), $someGate);

Gate::assert()

Gate::assert() is a static shortcut that validates a single value and either returns the filtered result or throws Verja\Exception\InvalidValue. Useful for assertions in controllers or service methods where throwing is the right behaviour.

use Verja\Gate;
use Verja\Exception\InvalidValue;

// Returns filtered value on success
$username = Gate::assert($input, 'required', 'trim', 'strLen:3:20');

// With filters that convert types
$age = Gate::assert($input, 'integer', 'between:0:150');

// Catching errors
try {
    $email = Gate::assert($input, 'required', 'emailAddress');
} catch (InvalidValue $e) {
    foreach ($e->errors as $error) {
        echo $error->key . ': ' . $error->message . "\n";
    }
}

InvalidValue carries both $e->errors (flat Error[]) and $e->errorMap (same flat array, keyed by '__scalar__' for single-value results).

Passing context

To supply a context array alongside the value (needed for cross-field validators like Equals), wrap the first argument:

Gate::assert(
    ['value' => $confirmation, 'context' => ['password' => $password]],
    'required',
    'equals:password'
);