Zod-like validation library for PHP 8.5 with full PHPStan type inference at level 10.
Core: Type<TValue> interface with execute(mixed, Context): TValue|Value::INVALID
Scalars: StringType
Complex: ArrayShapeType, RecordType
Modifiers: NullableType, CatchType, TransformType, PreProcessType, RefineType
PHPStan: Custom extensions for constructor type inference, execute() return types, and closure parameter types.
StringType:59-62 — When a constraint fails, a generic "String does not match constraints." error is added to context. The Constraint::$message property is never surfaced. Each failing constraint should add its own issue.
Your example API shows ->parse(someValue) but there's no parse method. Users currently must manually construct a ValidationContext and call execute(). Need:
- A
parse(mixed): TValuemethod that throws on failure - A
safeParse(mixed): ParseResult<TValue>that returns a result object - A
ValidationExceptionthat carries the structured issues - PHPStan extension for
parse()that returnsTValue(noValue::INVALID)
Your example shows Schema::string() but there's no factory. Currently requires new StringType(). A static factory makes the API much cleaner and is the natural place to add arrayShape(), int(), record(), etc.
IntType—intvalidation (withmin(),max(),positive(),negative())FloatType—floatvalidationBoolType—boolvalidationMixedType/AnyType— passthrough, useful in shapes where you don't care about a value's type
maxLength(int)pattern(string $regex)— regex matchingemail(),url(),uuid(),ip()— common format validators
ListType<T>— validateslist<T>(sequential integer keys)TupleType— validatesarray{string, int}(positional)
UnionType—Schema::union(Schema::string(), Schema::int())→string|intLiteralType—Schema::literal('active')→'active'EnumType—Schema::enum(Status::class)→Status
DefaultType— provides a default when value is missing/null (distinct fromCatchTypewhich catches validation failures)LazyType— for recursive/self-referencing schemas
Currently Issue is just a message string. For programmatic error handling and i18n, consider:
- Error code/type (e.g.,
'too_small','invalid_type') - Expected vs received metadata
- The path should be on the Issue itself, not just in the context's map
No test files exist yet. Need unit tests for each type and integration tests for composed schemas.
- Fix bugs (constraint messages, missing addIssue in ArrayShapeType)
- Add
parse()/safeParse()+ValidationException+ParseResult - Add
Schemafactory - Add
IntType,FloatType,BoolType - Add
ListType - Add
UnionType,LiteralType,EnumType - Add missing string constraints
- Add PHPStan extensions for new types
- Add tests
- Add
DefaultType,LazyType,PipeType(if needed)