laminas/laminas-hydrator
Laminas Hydrator provides flexible strategies to hydrate and extract data between objects and arrays. Supports reflection, class methods, naming strategies, and custom hydrators, making it easy to map entities, DTOs, and forms cleanly across your application.
Start by installing via Composer: composer require laminas/laminas-hydrator. Begin with the basic ArraySerializable hydrator for simple DTOs with toArray()/exchangeArray() support, or use ObjectProperty for standard public/protected property mapping. The core workflow is straightforward:
hydrate(array $data, $object) → populates an object from an arrayextract($object) → extracts an array from an objectFor initial use, hydrate a simple DTO from a request payload:
use Laminas\Hydrator\HydratorInterface;
use Laminas\Hydrator\ObjectProperty;
$hydrator = new ObjectProperty();
$user = $hydrator->hydrate($_POST, new UserDTO());
Check src/ for the primary classes: HydratorInterface, StrategyInterface, and NamingStrategyInterface. The README.md (if present) and docs/ folder (if available) should be your first reference — but given the package’s focus and stability, the interface contracts themselves are the primary documentation.
DTO Mapping: Use ObjectProperty or ArraySerializable hydrators for clean data transfer objects. Hydrate API request bodies or database result rows directly into typed DTOs.
Custom Value Conversion with Strategies: Override default scalar handling for non-trivial types. Example: a DateTimeStrategy to convert 2023-11-05 → DateTimeImmutable:
use Laminas\Hydrator\Strategy\DateTimeStrategy;
$hydrator->addStrategy('createdAt', new DateTimeStrategy('Y-m-d'));
Naming Strategy Translation: Bridge snake_case APIs/DB columns with camelCase properties using UnderscoreNamingStrategy:
use Laminas\Hydrator\NamingStrategy\UnderscoreNamingStrategy;
$hydrator = (new ObjectProperty())->setNamingStrategy(new UnderscoreNamingStrategy());
Composition & Filtering: Combine hydrators via delegation or use Filter\Exclude/IncludeByReflexion to omit internal properties (e.g., Entity::$id). Avoid magic — prefer explicit expose() definitions via a custom hydrator or ReflectionClass.
Nested Object Hydration: Use Aggregate hydrator to merge strategies across layers. For nested DTOs, register a StrategyInterface that recursively hydrates:
$hydrator->addStrategy('address', new AggregateAddressStrategy());
Standalone Usage: Decouple from frameworks. Use in CLI tools, background workers, or microservices where persistence is abstracted.
Property Visibility Matters: ObjectProperty only hydrates public properties by default. For protected/private, extend ObjectProperty and override getValue()/extractValue(), or use Reflection-based hydrator (Laminas\Hydrator\Reflection — note: this may require ext-reflection).
Strategy Order & Identity: Strategies are keyed by property name, not type. Conflicts arise if multiple hydrators use overlapping keys. Prefer addStrategy($name, $strategy) over setStrategy() when layering.
Type Coercion Risks: Hydration doesn’t validate types — only converts. A string "true" may hydrate into a boolean true, but null from DB can break strict-typed properties. Always combine with validation (e.g., laminas-validator) before persistence.
Naming Strategy Edge Cases: UnderscoreNamingStrategy doesn’t handle consecutive underscores (foo__bar → foo_bar) as expected. Test edge cases in JSON APIs that allow double-underscore keys.
Performance in Loops: Avoid creating hydrators per iteration. Reuse hydrator instances — strategies are stateless by design. Cache configured hydrators via factory/service container.
Extensibility Hooks: Override HydratorInterface::hydrate() to log or intercept hydration (e.g., for audit trails), or use PluginManager patterns if extending into Laminas MVC.
Missing Documentation? The package is stable and low-change. When docs are thin, inspect:
src/HydratorStrategy.php (the de facto interface)test/ files for real-world usage (e.g., DateTimeStrategyTest.php)How can I help you explore Laravel packages today?