Download the PHP package tetthys/commit-validator without Composer
On this page you can find all versions of the php package tetthys/commit-validator. It is possible to download/install these versions without Composer. Possible dependencies are resolved automatically.
Download tetthys/commit-validator
More information about tetthys/commit-validator
Files in tetthys/commit-validator
Package commit-validator
Short Description Framework-agnostic commit-time validator for session-aggregated payloads using DTO + PHP Attributes.
License MIT
Informations about the package commit-validator
tetthys/commit-validator
A fast, framework-agnostic validator designed for commit-time validation of session-aggregated payloads (multi-step forms), using DTOs + PHP Attributes and an optional lightweight DSL for commit-only rules.
This library is intentionally minimal: it validates the final, assembled data right before you “commit” it to your database (or any durable store).
- PHP: 8.4+
- Framework: none (pure PHP)
- Primary style: DTO + Attributes
- Secondary style: DSL (for commit-only overlays)
- No global helper is shipped: avoid name collisions; you can define your own optional helper (
cv()recommended).
Table of Contents
- Why this library exists
- Install
- Concepts
- Commit-time validation
- DTOs and Attributes
- Paths and error format
- Quick Start
- Recommended: define a local
cv()helper (optional)
- Recommended: define a local
- Defining DTOs
- Basic fields
- Nested DTOs
- Arrays of DTOs (Each)
- Collection constraints (Count)
- Validating
- Validating a DTO instance
- Adding commit-only rules (DSL overlays)
- Multi-step form workflow (session aggregation pattern)
- Step storage
- Final aggregation
- Commit validation
- Error handling
- Displaying errors
- Mapping paths to form field names (recommended pattern)
- Examples
- Example: product.images is required and must have 1..6 items
- Example: nested address + items list
- Example: draft vs commit strictness
- Performance notes
- API reference
- License
Why this library exists
Many validators are request-scoped: they validate a single request.
But multi-step forms often work like this:
- Step 1 validates and stores partial data (session, cache, temp DB row, etc.)
- Step 2 validates and stores more data
- Step N stores the last piece
- Commit: assemble the final payload and validate it holistically
At commit-time you need constraints like:
- "
product.imagesmust exist, and have 1..6 items" - "
shipping.addressmust be present ifshipping.methodisdelivery" - "
itemsmust have at least one item, and each item must be valid" - "Nested DTOs must satisfy their own rules"
tetthys/commit-validator focuses specifically on this commit-time validation problem.
Install
`
Requirements:
- PHP
^8.4
Concepts
Commit-time validation
“Commit-time validation” means you validate the final assembled payload, not each partial step in isolation.
This library assumes you already have a mechanism to store intermediate step data and to assemble it into a final array or DTO at commit time.
DTOs and Attributes
You define a DTO (data transfer object) and attach validation rules to its public properties using PHP Attributes:
Paths and error format
Validation errors are keyed by a dot path:
titleproduct.imagesproduct.images.0.urladdress.city
Errors are returned as a map:
This makes it easy to match errors back to nested form inputs and UI components.
Quick Start
1) Define DTO + Attributes
2) Assemble your final payload and create the DTO
3) Validate at commit-time
Recommended: define a local cv() helper (optional)
This package does not ship a global helper function to avoid collisions with user code and other packages.
If you like a short DSL entry point, define your own helper in your application (and autoload it however you prefer):
Then you can write:
Defining DTOs
Basic fields
Available built-in attributes:
#[Required(message?)]#[Length(min?, max?, message?)]#[Regex(pattern, message?)]#[InSet(values[], message?)]#[Count(min?, max?, message?)]
Example:
Nested DTOs
Use #[Nested(SomeDTO::class)] to validate a nested object recursively.
If address is present, the validator will validate AddressDTO and produce paths like:
address.cityaddress.street
Arrays of DTOs (Each)
Use #[Each(ItemDTO::class)] to validate every element in an array as a DTO.
Errors point to the exact index:
items.0.nameitems.3.name
Collection constraints (Count)
Use #[Count(min: X, max: Y)] on arrays to validate the number of items.
Validating
Validating a DTO instance
Adding commit-only rules (DSL overlays)
Attributes define your “always-on” rules.
Sometimes you want stricter commit-time constraints without affecting draft saves. For that, use a DSL overlay:
DSL methods:
cv()->required(message?)cv()->minLen(min, message?)cv()->maxLen(max, message?)cv()->regex(pattern, message?)cv()->inSet(values, message?)cv()->count(min?, max?, message?)->build()returns aRuleSet
Multi-step form workflow (session aggregation pattern)
This library does not manage session storage. It assumes you do.
Step storage
Example (pseudo-code):
Final aggregation
At commit time, you assemble the final structure:
You can normalize it (remove nulls, ensure arrays exist, etc.) before creating DTOs.
Commit validation
Construct DTO(s) from the final array and validate:
Error handling
Displaying errors
A simple rendering loop:
If you JSON-encode the Result, codes become strings:
Mapping paths to form field names (recommended pattern)
Many frontends use bracket-style names:
product[images][2][url]
While validator paths are dot-style:
product.images.2.url
A common pattern is to keep a mapping function:
Use this to attach errors to specific form controls.
Examples
Example: product.images is required and must have 1..6 items
This is the exact rule: required array, 1..6 items, and each item must be a valid ImageDTO.
Validate:
Example: nested address + items list
Paths:
address.cityitems.0.name
Example: draft vs commit strictness
Attributes always apply. For draft saves, you may want to accept looser rules and only enforce strict rules at commit.
Recommended pattern:
- Draft save: use a “draft DTO” with fewer Required/Count constraints, or
- Commit: overlay stricter constraints via DSL
Overlay example:
Performance notes
- Reflection is cached per DTO class internally.
- Validation is a simple rule loop over public properties.
- Nested/Each recursively validate children and produce precise paths.
API reference
CommitValidator::for(class-string $dtoClass): CommitValidator
Create a validator for a DTO class.
CommitValidator->with(string $property, RuleSet $rules): CommitValidator
Return a cloned validator with extra commit-only rules applied to $property.
CommitValidator->validate(object $dto): Result
Validate a DTO instance (plus any overlays).
Result->isValid(): bool
Returns true when no errors exist.
Result->errors(): array
Returns array<string, list<array{code: ErrorCode, message: string}>>
DSL
The package does not ship a global helper. Define cv() locally (optional):
Then use:
cv()->required(message?)cv()->minLen(min, message?)cv()->maxLen(max, message?)cv()->regex(pattern, message?)cv()->inSet(values, message?)cv()->count(min?, max?, message?)->build()→RuleSet
License
MIT