monkeyscloud / monkeyslegion-validation
Attribute-driven DTO binding and validation layer for the MonkeysLegion framework.
dev-main / 1.0.x-dev
2025-05-21 23:58 UTC
Requires
- php: ^8.4
- ext-json: *
- ext-mbstring: *
- laminas/laminas-diactoros: ^3.6
- monkeyscloud/monkeyslegion-core: ^1.0@dev
- monkeyscloud/monkeyslegion-di: dev-main
- psr/http-message: ^2.0 || ^1.0
- psr/http-server-handler: ^1.0
- psr/http-server-middleware: ^1.0
This package is auto-updated.
Last update: 2025-05-22 00:00:16 UTC
README
Attribute‑driven DTO binding & validation layer for the MonkeysLegion PHP framework.
✨ Features
- Attribute‑based constraints – ship with
#[NotBlank]
,#[Email]
,#[Length]
(extend in minutes) - Automatic binding – JSON body and query parameters → strongly‑typed DTO
- PSR‑15 middleware – intercepts the request, validates, and returns a 400 JSON error payload if needed
- Fail‑fast & zero‑magic – no doctrine/metadata proxies, only native PHP reflection
- Extensible – write a new constraint attribute in <10 LOC
- Lean footprint – depends only on PSR interfaces + Laminas Diactoros for JsonResponse
🛠 Requirements
Minimum | |
---|---|
PHP | 8.4 |
Extensions | ext-json , ext-mbstring |
Composer deps | psr/http-message , psr/http-server-handler , psr/http-server-middleware , laminas/laminas-diactoros |
All other MonkeysLegion packages (
core
,di
, …) are pulled in transitively.
🚀 Installation
composer require monkeyscloud/monkeyslegion-validation:^1.0@dev
Ensure your root composer.json allows dev stability while we are pre‑1.0:
{ "minimum-stability": "dev", "prefer-stable": true }
⚡ Quick Start
1. Define a DTO
<?php namespace App\Http\Dto; use MonkeysLegion\Validation\Attributes as Assert; final readonly class CreateUserRequest { public function __construct( #[Assert\NotBlank] #[Assert\Email] public string $email, #[Assert\NotBlank] #[Assert\Length(min: 8, max: 64)] public string $password, #[Assert\NotBlank] #[Assert\Pattern('/^[A-Z0-9_-]{3,10}$/')] public string $sku, #[Assert\Range(min: 0.01, max: 9999.99)] public float $price, #[Assert\Url] public string $productPage, #[Assert\UuidV4] public string $categoryId, ) {} }
2. Register services in your DI container
$container->register(\MonkeysLegion\Validation\ValidatorInterface::class, \MonkeysLegion\Validation\AttributeValidator::class); $container->register(\MonkeysLegion\Validation\DtoBinder::class) ->addArgument($container->get(\MonkeysLegion\Validation\ValidatorInterface::class));
3. Add the middleware to your PSR‑15 pipeline
use MonkeysLegion\Validation\Middleware\ValidationMiddleware; $pipeline->pipe(new ValidationMiddleware( $container->get(\MonkeysLegion\Validation\DtoBinder::class), [ // router‑name => DTO class 'user_create' => \App\Http\Dto\CreateUserRequest::class, ] ));
4. Use the validated DTO in your handler
public function createUser(ServerRequestInterface $request): ResponseInterface { /** @var \App\Http\Dto\CreateUserRequest $dto */ $dto = $request->getAttribute('dto'); $this->userService->register($dto->email, $dto->password); return new JsonResponse(['status' => 'created'], 201); }
When validation fails the client receives:
HTTP/1.1 400 Bad Request Content-Type: application/json { "errors": [ { "field": "email", "message": "Value must be a valid e-mail." }, { "field": "password", "message": "Length constraint violated." } ] }
🪄 Adding Custom Constraints
- Create an attribute class implementing
ConstraintInterface
(optional but recommended):
namespace MonkeysLegion\Validation\Attributes; use MonkeysLegion\Validation\ConstraintInterface; #[\Attribute(\Attribute::TARGET_PROPERTY)] final class UuidV4 implements ConstraintInterface { public function __construct( public string $message = 'Value must be a valid UUIDv4.' ) {} }
- Add a check inside
AttributeValidator::validate()
:
if ($instance instanceof Assert\UuidV4 && !preg_match('/^[0-9a-f]{8}-[0-9a-f]{4}-4[0-9a-f]{3}-[89ab][0-9a-f]{3}-[0-9a-f]{12}$/i', $value)) { $errors[] = new ValidationError($prop->getName(), $instance->message); }
That’s it—#[UuidV4]
is now usable on any DTO property.
🗺 Roadmap
- 🌐 Localisable validation messages
- 🔌 Symfony Validation bridge
- 📚 Constraint composition (
#[Assert\All(new Assert\Email())]
‑style) - 🧰 CLI generator for DTO & constraint scaffolding
🙌 Contributing
- Fork & create a feature branch.
- Follow PSR‑12 coding standards.
- Add unit tests (
vendor/bin/phpunit
). - Open a PR.
📄 License
Released under the MIT License © 2025 MonkeysCloud.