Skip to content

Errors and ValidationResult

Every call to validate() returns a Verja\ValidationResult value object.

ValidationResult

$result = $gate->validate($data);

$result->valid    // bool — true if all validation passed
$result->data     // mixed — filtered, validated data (only meaningful when valid)
$result->errors   // array — nested error structure
$result->errorMap // array — flat dot-notation error map

$result->data

On success, data contains the filtered and validated values. Only properties that were defined on the gate are included — undeclared keys in the input are dropped automatically. Optional properties that were absent are also absent from data.

$gate = (new Gate())
    ->string('name', 'required')
    ->int('age');

$result = $gate->validate(['name' => 'Alice', 'age' => '30', 'role' => 'admin']);
// $result->data === ['name' => 'Alice', 'age' => 30]
// 'role' is silently dropped (not defined on the gate)
// 'age' is cast to int by the Integer filter that ->int() applies

The Error object

Each validation failure produces a Verja\Error:

$error->key        // string  — machine-readable code, e.g. 'STRLEN_TOO_SHORT'
$error->message    // string  — human-readable message, e.g. 'length should be at least 3'
$error->parameters // array   — structured data: always includes 'value', plus validator-specific fields

Example:

// For ->string('username', 'strLen:3:20') with value 'ab':
$error->key        === 'STRLEN_TOO_SHORT'
$error->message    === 'length should be at least 3'
$error->parameters === ['value' => 'ab', 'min' => 3, 'max' => 20]

Error keys for all built-in validators are listed on the validators page.

$result->errors — nested structure

errors reflects the nesting of the validated data. For a flat gate it's [fieldName => [Error, ...]]. For nested structures it goes deeper:

// ['author' => ['email' => [Error, ...]]]
$result->errors['author']['email'][0]->message;

$result->errorMap — flat dot-notation

errorMap is the same information flattened to a single level with dot-separated paths. This is what you usually want for API responses or passing errors to a frontend:

// ['author.email' => [Error, ...], 'tags.1' => [Error, ...]]
foreach ($result->errorMap as $path => $errors) {
    echo "$path: " . $errors[0]->message . "\n";
}

The special key __scalar__ is used for errors on the root value itself (e.g. when a Gate receives a non-structured input, or a PropertyGate fails a validator directly).

JSON serialization for APIs

Error is a plain object — serialize it however your framework expects. A typical JSON API response might look like:

if (!$result->valid) {
    return new JsonResponse([
        'errors' => array_map(
            fn($errors) => array_map(
                fn($e) => ['key' => $e->key, 'message' => $e->message],
                $errors
            ),
            $result->errorMap
        ),
    ], 422);
}

Which produces:

{
  "errors": {
    "author.email": [
      { "key": "NO_EMAIL_ADDRESS", "message": "value should be a valid email address" }
    ],
    "tags.1": [
      { "key": "STRLEN_TOO_SHORT", "message": "length should be at least 2" }
    ]
  }
}

Throwing on failure

All gate types expose assertValid() as an alternative to validate(). It throws Verja\Exception\InvalidValue on failure and returns $result->data on success:

try {
    $data = $gate->assertValid($input);
} catch (Verja\Exception\InvalidValue $e) {
    // $e->errors    — same as $result->errors
    // $e->errorMap  — same as $result->errorMap
}