Skip to content

Converters reference (Stage 1)

Converters are the first stage of the pipeline. They convert raw input (strings, mixed types from form submissions or JSON decoding) to a typed PHP value before any validators run.

A converter returns one of three sealed signals:

Signal Meaning
valid($value) Conversion succeeded — typed value continues to Stage 3 (filters)
null() Input is absent/empty — continues to Stage 2 (null policy)
invalid($error) Bad format — pipeline stops immediately with an error

Use use Verja\Verja as v or use Verja\Converter to access converters.


Integer

'integer', 'int', v::integer(), new Converter\Integer()

Converts numeric strings and integers to int. Accepts any value for which (int)$value equals $value + 0 (i.e. the value represents a whole number). Absent/empty input (null or '') signals null() and proceeds to the null policy stage.

->int('age', 'between:0:150')
// '42' → 42, '' → null policy, 'abc' → error NO_INTEGER

Error key: NO_INTEGER.


Boolean

'boolean', 'bool', v::boolean(), new Converter\Boolean($stringTrue = [], $stringFalse = [], $overwrite = false)

Converts to PHP bool. Accepts:

  • Native bool — passes through
  • int 1 / 0 — converted to true / false
  • Strings (case-insensitive) by default:
  • truthy: '1', 'true', 't', 'yes', 'y'
  • falsy: '0', 'false', 'f', 'no', 'n'

Pass $stringTrue / $stringFalse to add extra accepted representations. Pass $overwrite = true to replace the defaults entirely.

->boolean('active')
// '1' → true, 'false' → false, 'maybe' → error NO_BOOLEAN

new Converter\Boolean(['on'], ['off'], true)
// 'on' → true, 'off' → false, 'yes' → error (defaults replaced)

Error key: NO_BOOLEAN.


Numeric

'numeric', v::numeric(), new Converter\Numeric($decimalPoint = '.')

Converts numeric strings to int (if no decimal part) or float. Native int and float values pass through unchanged.

Pass $decimalPoint to support alternative decimal separators:

new Converter\Numeric(',')
// '3,14' → 3.14, '1.000,50' → 1000.5 (thousands dot stripped)

Error key: NO_NUMERIC.


DateTime

'dateTime', v::dateTime(), new Converter\DateTime($timeZone = null, $format = null, $strict = false)

Converts a string to a PHP \DateTime object.

  • Without $format: parses any string accepted by PHP's DateTime constructor.
  • With $format: requires the value to match exactly (delegates to DateTime::createFromFormat()).
  • $strict = true: additionally rejects overflow dates (e.g. 2025-01-32).
  • $timeZone: accepts a \DateTimeZone instance, a timezone name string, or a UTC offset integer.

Native \DateTime / \DateTimeImmutable values pass through unchanged.

->date('published_at')
// '2024-03-15' → DateTime, 'abc' → error NO_DATE

new Converter\DateTime('UTC', 'Y-m-d')
// '2024-03-15' → DateTime in UTC, '15.03.2024' → error NO_FORMATTED_DATE

Error keys: NO_DATE, NO_FORMATTED_DATE.


Json

'json', v::json(), new Converter\Json($type = null)

Decodes a JSON string to a PHP value. Already-decoded values (arrays, integers, etc.) pass through unchanged. 'null' JSON string and absent/empty input both signal null().

$type optionally asserts or further converts the decoded value:

$type Accepted decoded value Delegates to
null (default) any
'array' indexed array
'object' associative array
'string' string
'integer' integer Converter\Integer
'numeric' number Converter\Numeric
'bool' boolean Converter\Boolean
'datetime' date string Converter\DateTime
->any('payload', v::json(), new Gate()->int('a'))
// '{"a":1}' → ['a' => 1], validated as a gate with integer property 'a'

->any('tags', v::json('array'), v::min(1))
// '["php","oop"]' → ['php', 'oop'], '{"key":"val"}' → error NO_ARRAY

Error keys: INVALID_JSON, NO_ARRAY, NO_OBJECT, NO_STRING.


Custom converters

Implement Verja\ConverterInterface (or extend Verja\Converter), then register the namespace so string definitions resolve automatically:

use Verja\ConvertResult;
use Verja\ConverterInterface;

class UlidConverter implements ConverterInterface
{
    public function convert(mixed $value): ConvertResult
    {
        if ($value === null || $value === '') {
            return ConvertResult::null();
        }
        if (!preg_match('/^[0-9A-Z]{26}$/', $value)) {
            return ConvertResult::invalid(new Error('NO_ULID', $value, 'must be a valid ULID'));
        }
        return ConvertResult::valid($value);
    }
}

Verja::addConverterNamespace('\\App\\Converter');
// now 'ulid' resolves to App\Converter\Ulid

See custom validators and filters for the full guide on extending the library.