Weave Code
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

Object Hydrator Laravel Package

eventsauce/object-hydrator

Magic-less object hydration and serialization for PHP. Map arrays/decoded JSON to DTOs, commands, queries, and events by inspecting constructors and public getters—no private-property reflection. Supports custom keys, casting, and optional code generation for speed.

View on GitHub
Deep Wiki
Context7

Getting Started

Minimal Setup

  1. Installation:

    composer require eventsauce/object-hydrator
    

    Add to composer.json if using a monorepo or custom setup:

    "repositories": [{
      "type": "vcs",
      "url": "https://github.com/EventSaucePHP/ObjectHydrator"
    }]
    
  2. Basic Usage:

    use EventSauce\ObjectHydrator\Hydrator;
    use EventSauce\ObjectHydrator\Exception\HydrationFailed;
    
    $hydrator = new Hydrator();
    $data = ['name' => 'John', 'age' => 30];
    $user = $hydrator->hydrate(User::class, $data);
    
  3. First Use Case: Convert an API response or database row into a strict Laravel Eloquent model or DTO:

    $apiResponse = json_decode($httpResponse->getBody(), true);
    $user = $hydrator->hydrate(User::class, $apiResponse);
    

Implementation Patterns

Core Workflows

  1. DTO Hydration: Use for strict, immutable data transfer objects:

    class UserDTO {
        public function __construct(
            public string $name,
            public int $age,
            public ?string $email = null
        ) {}
    }
    
    $dto = $hydrator->hydrate(UserDTO::class, $data);
    
  2. Eloquent Model Hydration: Bypass Laravel’s mass assignment protection:

    $user = $hydrator->hydrate(User::class, $data);
    $user->save(); // No need for `$fillable` or `$guarded`
    
  3. Nested Hydration: Hydrate collections or nested objects:

    $data = ['posts' => [['title' => 'Hello'], ['title' => 'World']]];
    $user = $hydrator->hydrate(UserWithPosts::class, $data);
    

Integration Tips

  • Laravel Service Providers: Bind the hydrator as a singleton in AppServiceProvider:

    $this->app->singleton(Hydrator::class, fn() => new Hydrator());
    
  • API Request Validation: Combine with Laravel’s ValidatesRequests:

    public function store(Request $request) {
        $validated = $request->validate([...]);
        $user = resolve(Hydrator::class)->hydrate(User::class, $validated);
    }
    
  • Event Dispatching: Hydrate event payloads directly:

    $event = $hydrator->hydrate(UserRegistered::class, $payload);
    event($event);
    

Gotchas and Tips

Pitfalls

  1. Type Mismatches:

    • Hydrator throws HydrationFailed on type mismatches (e.g., passing "30" to an int field).
    • Fix: Use Hydrator::withTypeCasting() to auto-cast strings to integers/booleans:
      $hydrator = new Hydrator(['cast' => true]);
      
  2. Circular References:

    • Fails on recursive object structures (e.g., UserPostUser).
    • Fix: Use Hydrator::withCircularReferenceHandling() (requires PHP 8.1+):
      $hydrator = new Hydrator(['circular_reference_handling' => 'ignore']);
      
  3. Private/Protected Properties:

    • Hydrator respects visibility but cannot set private/protected properties directly.
    • Fix: Use setters or Hydrator::withPropertyAccess() (PHP 8.0+):
      $hydrator = new Hydrator(['property_access' => PropertyAccess::PUBLIC_AND_PRIVATE]);
      

Debugging

  • Enable Strict Mode: Set ['strict' => true] to fail on unknown properties (useful for DTOs):

    $hydrator = new Hydrator(['strict' => true]);
    
  • Custom Hydrators: Extend Hydrator to add logic:

    class CustomHydrator extends Hydrator {
        protected function hydrateProperty($property, $value, $object) {
            if ($property === 'email') {
                $value = strtolower($value);
            }
            return parent::hydrateProperty($property, $value, $object);
        }
    }
    

Extension Points

  1. Custom Type Casting: Override Hydrator::castValue() to handle custom types (e.g., Carbon instances):

    $hydrator = new Hydrator(['cast' => function($value, $type) {
        return $type === 'DateTime' ? Carbon::parse($value) : null;
    }]);
    
  2. Post-Hydration Callbacks: Use Hydrator::withPostHydrateCallback():

    $hydrator = new Hydrator(['post_hydrate' => fn($object) => $object->boot()]);
    
  3. Laravel Collections: Hydrate collections with Collection::mapInto():

    $users = collect($data)->mapInto(User::class);
    // Internally uses a hydrator-like pattern.
    
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.
davejamesmiller/laravel-breadcrumbs
artisanry/parsedown
christhompsontldr/phpsdk
enqueue/dsn
bunny/bunny
enqueue/test
enqueue/null
enqueue/amqp-tools
milesj/emojibase
bower-asset/punycode
bower-asset/inputmask
bower-asset/jquery
bower-asset/yii2-pjax
laravel/nova
spatie/laravel-mailcoach
spatie/laravel-superseeder
laravel/liferaft
nst/json-test-suite
danielmiessler/sec-lists
jackalope/jackalope-transport