Weave Code
Weaver
Helps Laravel developers discover, compare, and choose open-source packages. See popularity, security, maintainers, and scores at a glance to make better decisions.
Feedback
Share your thoughts, report bugs, or suggest improvements.
Subject
Message

Hydrator Validator Laravel Package

yiisoft/hydrator-validator

Integrates Yii Hydrator with Yii Validator to validate input data while hydrating typed objects and DTOs. Map arrays into objects and enforce validation rules in one step, reducing boilerplate and keeping data checks close to object construction.

Deep Wiki
Context7

Getting Started

Minimal steps:

  1. Install the package; it pulls in yiisoft/hydrator and yiisoft/validator as dependencies:
    composer require yiisoft/hydrator-validator
    
  2. Register the hydrator in a service provider. There is no Laravel auto-discovery for this package, so this is manual:
    use Yiisoft\Hydrator\HydratorInterface;
    use Yiisoft\Hydrator\Validator\HydratorValidatorFactory;
    use Yiisoft\Validator\Validator;
    use Yiisoft\Validator\ValidatorInterface;
    
    $this->app->singleton(ValidatorInterface::class, fn () => new Validator());
    $this->app->singleton(HydratorInterface::class, fn ($app) =>
        (new HydratorValidatorFactory())->create($app->make(ValidatorInterface::class))
    );
    
    Check the factory signature in src/HydratorValidatorFactory.php for the exact named arguments in the version you install.
  3. Where to look first: README.md, then src/HydratorValidator.php, src/Attribute/Validate.php, and the tests/ directory. The tests are the most reliable documentation for how raw data versus hydrated objects are validated.

First use case — replace an ad-hoc FormRequest with a validated DTO:

use Yiisoft\Hydrator\Validator\Attribute\Validate;
use Yiisoft\Validator\Rule\Email;
use Yiisoft\Validator\Rule\Length;
use Yiisoft\Validator\Rule\Required;

final class ContactData
{
    public function __construct(
        #[Validate]
        #[Required]
        #[Length(min: 2, max: 100)]
        public readonly string $name = '',
        #[Validate]
        #[Required]
        #[Email]
        public readonly string $email = '',
        #[Validate]
        #[Length(max: 1000)]
        public readonly string $message = '',
    ) {}
}
public function store(Request $request, HydratorInterface $hydrator)
{
    try {
        $data = $hydrator->hydrate(ContactData::class, $request->all());
    } catch (ValidationException $e) {
        return response()->json(['errors' => $e->getResult()->getErrorMessages()], 422);
    }

    // $data is fully hydrated and validated
}

If you only need basic array-to-object mapping, yiisoft/hydrator alone is enough. This package is specifically for the case where you want the hydration step and the validation step to be one operation, and where validation should see the raw payload, not just the hydrated object.

Implementation Patterns

Validated DTO at the HTTP boundary. Keep hydration in the controller (or a small action class) and pass the resulting readonly DTO into your service layer. The DTO becomes a proof-of-validation token: downstream code can trust its types and values without re-checking.

Raw-data validation before or alongside hydration. The core reason this package exists: if you validate only the hydrated object, missing input keys silently become property defaults. #[Validate] should be applied so rules see the original array values (or the package version's raw-data flag). Use Required on fields where an empty string default would otherwise pass.

Wrap ValidationException once. Create a base controller or a ValidatedRequest adapter that catches Yiisoft\Hydrator\Validator\Exception\ValidationException, converts getResult()->getErrorMessages() into Laravel's MessageBag, and throws Illuminate\Validation\ValidationException::withMessages(...). Then your controllers stay clean and your API returns Laravel-shaped 422 responses.

Reuse Yii validator rules as attributes. Rules like #[Required], #[Length], #[Email], and #[Regex] are attribute classes from yiisoft/validator. For custom business rules, implement Yiisoft\Validator\RuleInterface and attach it the same way. This is the main extension point for domain-specific checks (e.g., #[UniqueSku]).

Test the DTO directly, not through HTTP. Because the DTO is just a class with attributes, you can unit-test it:

$result = (new Validator())->validate($dto);
$this->assertFalse($result->isValid());

Feature-test the controller with invalid payloads only to verify the exception-to-422 mapping.

Nested DTOs. Hydration of nested objects and arrays requires explicit wiring in the hydrator (a custom attribute handler or a factory). Don't assume array<ItemData> maps automatically; verify with a small unit test first, since nested validation often needs to be declared on the parent as well.

Layer separation. Use the hydrator only at the edge. Don't hydrate Eloquent models from request data — hydrate DTOs, then explicitly map DTOs to models. This keeps mass-assignment risk out of the picture.

Gotchas and Tips

  • No Laravel integration ships with it. You must register the binding, resolve the hydrator, and translate ValidationException yourself. Budget a small adapter class for this.
  • The exception is not Laravel's. Yiisoft\Hydrator\Validator\Exception\ValidationException will bubble up as a 500 unless you catch it. Map it in App\Exceptions\Handler or a base controller.
  • Raw vs. hydrated semantics are the whole point — and the whole trap. With typed constructor properties and defaults, a missing key can hydrate fine and validate fine. Confirm that #[Validate] in your pinned version checks the raw array for presence rules; add an explicit Required and a test that omits the key.
  • Type errors can beat validation. If the payload sends an array where a string is expected, hydration can throw a TypeError or a hydration exception before the validator ever runs. Catch both the hydration exception and the validation exception at the boundary.
  • Only marked properties are validated. #[Validate] is opt-in. A newly added constructor parameter without the attribute is silently unvalidated. Consider a coding-standard rule or a test that enumerates DTO parameters.
  • Error message extraction differs from Laravel. getErrorMessages() returns a flat list keyed by property/rule path, not Laravel's nested field => [messages] structure. Normalize it in your adapter if clients depend on Laravel's JSON error shape.
  • Reflection cost. Hydration and attribute validation use reflection. Register the hydrator and validator as singletons; don't instantiate per request in a hot path.
  • Attribute ordering and handler registration. If you add custom hydrator attribute handlers, check the order in which they run. A handler that transforms a value can affect what the validator sees.
  • Debug with the Result. In development, log $e->getResult()->getErrors() rather than just the exception message; it carries the rule-level detail.
  • Pin the version. The package is small (14 stars) and young, with the last release in December 2025. Attribute names and factory signatures can move between minors. Pin a minor version and read the changelog before upgrading.
  • Don't mix validation systems. Running Laravel's $request->validate() and this hydrator on the same payload creates two sources of truth and duplicated rules. Pick one per DTO and stick to it.
  • When not to use it: if your project is already idiomatic Laravel, FormRequest plus $request->validated() into a DTO is simpler and better supported. This package earns its place when you want framework-agnostic DTO validation shared with non-Laravel code, or you are already using yiisoft/validator rules.
Weaver

How can I help you explore Laravel packages today?

Conversation history is not saved when not logged in.
Prompt
Add packages to context
No packages found.
3mdikram/worldmoneywords
snowsoft/config
itmosoft/laravel-subscriptions
larva/laravel-ai-qwen
diephp/sequences
users-au/socialite-provider
twidpay/twid-logger
mrnewport/laravel-plaid
mrnewport/laravel-repo
mrnewport/laravel-docsign
mrnewport/laravel-stow
mrnewport/laravel-flow
mrnewport/laravel-priceable
mrnewport/laravel-nestedterms
fredmeng/laravel-apidoc-generator
itstructure/laravel-multilingual-tools
pdustdar/elasticsearch
markupai/php-sdk
rlacerda83/lumem-microservice-shipment
uni-method/symfony-lib