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

Data Model Laravel Package

zero-to-prod/data-model

Reflection-based PHP data models that hydrate typed objects from arrays with a single from($data) call. Use #[Describe] attributes to define casting, validation, defaults, nullable/required rules, and assignments—keeping mapping logic predictable, readable, and verifiable.

View on GitHub
Deep Wiki
Context7

Technical Evaluation

Architecture Fit

  • Strong alignment with Laravel’s DTO/value-object patterns: The package’s declarative #[Describe] attribute system mirrors Laravel’s validation and casting conventions (e.g., Castable, Validatable), reducing cognitive friction for teams already using Laravel’s ecosystem.
  • Complementary to Laravel’s Eloquent: Recursive hydration of nested objects aligns with Eloquent’s toArray()/toJson() patterns, enabling seamless integration with API responses or database hydration.
  • Type safety as a first-class citizen: Leverages PHP 8+ features (attributes, union types) to enforce contracts at compile time, reducing runtime errors—a critical advantage in Laravel’s type-hinted services layer.
  • Decouples business logic from hydration: Centralizes validation/casting logic in attributes, enabling cleaner service classes and reducing boilerplate in controllers/repositories.

Integration Feasibility

  • Minimal invasiveness: The DataModel trait requires no base class or interface, making adoption straightforward for existing Laravel models or DTOs.
  • Laravel-specific extensions: The package’s DataModelHelper and Transformable packages suggest potential for custom Laravel integrations (e.g., DataModel-aware form requests, API resource transformations).
  • Compatibility with Laravel’s DI container: Static from() calls can be wrapped in container bindings (e.g., App\Services\UserService::from()) for dependency injection.
  • Database integration: Recursive hydration enables direct mapping from database results (e.g., Model::query()->get()->map(fn ($m) => User::from($m->toArray()))), though ORM-specific optimizations (e.g., eager loading) may still be needed.

Technical Risk

  • Performance overhead: Reflection-based attribute parsing and recursive hydration could introduce latency in high-throughput APIs. Benchmarking against manual hydration (e.g., array_map) is recommended.
  • Attribute bloat: Overuse of #[Describe] with complex hooks (e.g., nested pre/post logic) may reduce readability. Teams should enforce a "simple by default" convention.
  • Laravel-specific edge cases:
    • Eloquent models: Hydrating from Eloquent collections may conflict with Laravel’s lazy loading or accessors/mutators.
    • Validation: The package’s validation is declarative but not tied to Laravel’s Validator; teams may need to duplicate rules or build bridges (e.g., via DataModelHelper).
    • Caching: Recursive hydration could bypass Laravel’s query caching (e.g., Model::remember()). Custom caching layers may be needed for nested objects.
  • PHP version dependency: Requires PHP 8.1+ (for attributes) and 8.5+ for first-class callables. Laravel’s LTS support (8.110+) aligns, but legacy projects may need polyfills.

Key Questions

  1. Adoption scope:
    • Will this replace all manual DTO hydration in the codebase, or supplement it (e.g., for APIs only)?
    • How will teams balance #[Describe] attributes with Laravel’s existing #[Cast]/#[Attribute] patterns?
  2. Performance:
    • Are there critical paths where hydration latency is unacceptable? If so, should manual hydration be retained for those cases?
  3. Validation strategy:
    • Will Laravel’s Validator remain the source of truth, or will DataModel attributes replace it? If hybrid, how will conflicts be resolved?
  4. Testing:
    • How will property-level hooks (e.g., pre/post) be tested? Mocking reflection attributes may require custom test utilities.
  5. Tooling:
    • Should IDE plugins (e.g., PHPStorm) be configured to recognize DataModel attributes for better autocompletion?
  6. Migration:
    • Which classes will be prioritized for DataModel adoption? Start with DTOs/API responses or core domain models?

Integration Approach

Stack Fit

  • Laravel ecosystem:
    • APIs: Ideal for request DTOs, API responses, and GraphQL input types. Replace manual json_decode() + array_map with DataModel::from($request->all()).
    • Validation: Pair with Laravel’s FormRequest or Validator for hybrid validation (e.g., #[Describe(['required'])] + rules()).
    • Eloquent: Use for query results or API resources (e.g., UserResource::from($user)). Avoid mixing with Eloquent’s mutators/accessors unless explicitly bridged.
    • Queues/Jobs: Hydrate job payloads declaratively (e.g., ProcessOrder::from($payload)).
  • Third-party integrations:
    • API clients: Hydrate responses from Guzzle/HTTP clients (e.g., GitHubUser::from($client->fetch())).
    • Event dispatching: Convert event payloads to strongly typed objects (e.g., OrderCreatedEvent::from($data)).
  • Testing:
    • Generate test fixtures from arrays (e.g., User::from(['name' => 'Test']) in PHPUnit).

Migration Path

  1. Pilot phase:
    • Start with non-critical DTOs (e.g., API request/response models, event payloads).
    • Replace manual hydration in controllers/services with DataModel::from().
    • Example:
      // Before
      $user = new User($request->input('name'), $request->input('age'));
      
      // After
      $user = User::from($request->all());
      
  2. Validation alignment:
    • Audit existing FormRequest/Validator rules. Replace redundant checks with #[Describe(['required', 'nullable'])].
    • Use DataModelHelper to bridge gaps (e.g., attach Laravel validation errors to DataModel exceptions).
  3. Eloquent integration:
    • For query results, create a DataModel-aware repository layer:
      class UserRepository {
          public function find(int $id): User {
              return User::from((new UserModel)->find($id)->toArray());
          }
      }
      
    • Avoid mixing DataModel with Eloquent’s magic methods (e.g., snake_case attributes).
  4. Incremental adoption:
    • Use composer scripts to auto-generate documentation for DataModel classes:
      {
        "scripts": {
          "post-autoload-dump": "zero-to-prod-data-model ./docs/datamodels"
        }
      }
      
    • Train teams on attribute conventions (e.g., prefer #[Describe(['cast' => 'trim'])] over manual trim() calls).

Compatibility

Component Compatibility Notes
Laravel 10+ Full support (PHP 8.1+).
Eloquent Models Avoid mixing DataModel with Eloquent’s attributes, casts, or accessors. Use separate classes.
Laravel Validation No native integration; use DataModelHelper or custom validation bridges.
API Resources Replace JsonResource toArray() with DataModel::from($model)->toArray().
Queues/Jobs Hydrate job payloads via DataModel::from($payload).
Testing (PHPUnit) Works natively; use DataModel for test data factories.
Caching Recursive hydration bypasses Laravel’s query cache. Add custom caching for nested objects.

Sequencing

  1. Phase 1: DTOs and APIs
    • Replace manual DTO hydration in controllers, API resources, and event handlers.
    • Tools: DataModelHelper for array/collection transformations.
  2. Phase 2: Validation
    • Migrate FormRequest rules to #[Describe] where possible.
    • Tools: Custom exception handlers to map DataModel errors to Laravel’s validation response format.
  3. Phase 3: Eloquent
    • Introduce DataModel-aware repositories for query results.
    • Tools: Query builder extensions to return DataModel instances.
  4. Phase 4: Testing
    • Replace hardcoded test data with DataModel::from() calls.
    • Tools: DataModelFactory for test data generation.
  5. Phase 5: Optimization
    • Benchmark critical paths; optimize with manual hydration where needed.
    • Tools: Xdebug profiling to identify bottlenecks.

Operational Impact

Maintenance

  • Pros:
    • Reduced boilerplate: #[Describe] attributes centralize validation/casting logic, reducing maintenance in constructors/factories.
    • Self-documenting: Attributes serve as living documentation (e.g., #[Describe(['cast' => 'strtoupper'])] clarifies intent).
    • Consistent behavior: Resolution order and precedence rules prevent ad-hoc logic drift.
  • Cons:
    • Attribute sprawl: Overuse of Describe keys (e.g., pre/post hooks) may make classes harder to read.
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.
nexmo/api-specification
capell-app/block-library
axium/identity
cetria/laravel-dummy-models
cetria/reflection-helper
agropredict/sso-auth-bundle
evolvestudio/spam-protection
datacore/hub-sdk
develia/commons
cuci/prototurk-sdk
cuci/prototurk-sdk-symfony
develia/geo-bundle
dreamzy/livewire-charts
touchestate-sdk/php-sdk
ecotone/kafka
22h/doctrine-garbage-collection-bundle
agtp/agtp-php
agtp/mod-php
splash/sonata-admin
splash/metadata