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

Easy Hydrator Laravel Package

eag/easy-hydrator

View on GitHub
Deep Wiki
Context7

Getting Started

Minimal Setup

  1. Installation:

    composer require eag/easy-hydrator
    

    No additional configuration is required unless using Symfony bundles (add to config/bundles.php if applicable).

  2. First Use Case: Hydrate a simple array into a DTO/Value Object:

    use EAG\EasyHydrator\ArrayToValueObjectHydrator;
    
    $hydrator = new ArrayToValueObjectHydrator();
    $person = $hydrator->hydrate([
        'name' => 'John Doe',
        'age' => 30,
        'metAt' => '2023-01-01T12:00:00+00:00'
    ], Person::class);
    

Where to Look First

  • Class: ArrayToValueObjectHydrator (core hydrator).
  • README: Focus on the "Usage" section for examples.
  • Tests: Test files demonstrate edge cases (e.g., nested objects, custom types).

Implementation Patterns

Core Workflow

  1. Dependency Injection: Bind the hydrator in Laravel’s service container (e.g., AppServiceProvider):

    $this->app->bind(ArrayToValueObjectHydrator::class, fn() => new ArrayToValueObjectHydrator());
    

    Use it in repositories/services:

    public function __construct(private ArrayToValueObjectHydrator $hydrator) {}
    
  2. Hydration Pipeline:

    • Input: Associative array (keys match constructor parameter names).
    • Output: Instantiated object with constructor-injected properties.
    • Example:
      $user = $this->hydrator->hydrate($request->all(), User::class);
      
  3. Nested Objects: Automatically hydrates nested arrays if the target class has typed properties:

    class Address {
        public function __construct(public string $street, public string $city) {}
    }
    
    class User {
        public function __construct(public string $name, public Address $address) {}
    }
    
    $user = $hydrator->hydrate([
        'name' => 'Alice',
        'address' => ['street' => '123 Main', 'city' => 'Metropolis']
    ], User::class);
    
  4. Custom Object Creation: Override default behavior via setObjectFactory:

    $hydrator->setObjectFactory(fn(string $class) => new $class(...));
    

Integration Tips

  • Form Requests: Hydrate validated input directly:
    $validated = $request->validate([...]);
    $model = $hydrator->hydrate($validated, CreateUserRequest::class);
    
  • API Responses: Use for DTOs in JSON API responses:
    return response()->json($hydrator->hydrate($data, UserResponse::class));
    
  • Caching: Enable caching for repeated hydrations (e.g., in a loop):
    $hydrator->enableCache();
    

Gotchas and Tips

Pitfalls

  1. Case Sensitivity: Array keys must match constructor parameter names exactly (case-sensitive). Fix: Use array_change_case or normalize keys before hydrating.

  2. Unsupported Types:

    • Custom Types: Only works with PHP 8.0+ type declarations (e.g., DateTimeInterface). Fix: Implement __toString() or a custom type mapper.
    • Non-Constructor Properties: Fix: Use setters or setPropertyMapper for dynamic properties.
  3. Circular References: Nested objects with circular references (e.g., User->Address->User) will fail. Fix: Break cycles or use lazy loading.

  4. Symfony Bundle Overhead: The EasyHydratorBundle adds minimal value for Laravel. Skip it unless using Symfony components.

Debugging

  • Validation Errors: Enable strict mode to catch mismatches:
    $hydrator->setStrictMode(true); // Throws exceptions on missing keys/types.
    
  • Type Mismatches: Check hydrate() return values for null (indicates failure). Use try-catch:
    try {
        $obj = $hydrator->hydrate($data, User::class);
    } catch (HydrationException $e) {
        Log::error($e->getMessage());
    }
    

Extension Points

  1. Custom Type Handling: Extend TypeMapper for unsupported types (e.g., UUIDs):
    $hydrator->setTypeMapper(new CustomTypeMapper());
    
  2. Property Mapping: Override default property assignment:
    $hydrator->setPropertyMapper(fn(string $property, $value) => "custom_$property");
    
  3. Performance:
    • Disable caching for one-off hydrations:
      $hydrator->disableCache();
      
    • Pre-instantiate hydrators for high-frequency use (e.g., API routes).

Laravel-Specific Tips

  • Service Container: Tag the hydrator for lazy loading:
    $this->app->tag(ArrayToValueObjectHydrator::class, ['hydrators']);
    
  • Testing: Mock the hydrator in unit tests:
    $mockHydrator = Mockery::mock(ArrayToValueObjectHydrator::class)
        ->shouldReceive('hydrate')
        ->once()
        ->andReturn(new User(...));
    
  • Artisan Commands: Use for bulk data imports:
    $hydrator = app(ArrayToValueObjectHydrator::class);
    foreach ($csvData as $row) {
        $model = $hydrator->hydrate($row, Product::class);
        $model->save();
    }
    
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.
hamzi/corewatch
minionfactory/raw-hydrator
hexters/coinpayment
rjcodes/rjcms
act-training/laravel-permissions-manager
alimarchal/laravel-chart-of-accounts
babenkoivan/elastic-scout-driver
mkwebdesign/filament-watchdog-v5
renatomarinho/laravel-page-speed
zedmagdy/filament-business-hours
renatovdemoura/blade-elements-ui
devgeek/beacon-admin
benjamin-rqt/data-watcher-bundle
atriumphp/atrium
sandermuller/package-boost-laravel
sandermuller/boost-skills
redaxo/core
yusufgenc/filament-api-forge
l3aro/rating-star-for-filament
leek/filament-subtenant-scope