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

Type-safe PHP data models that hydrate from arrays/JSON via a single from($data) call. Uses reflection, type hints, and #[Describe] attributes for defaults, required/nullable rules, casting, and assignment—ideal for APIs, DB rows, and user input.

View on GitHub
Deep Wiki
Context7

Technical Evaluation

Architecture Fit

  • Type-Safety & DTOs: Aligns perfectly with Laravel’s growing emphasis on type safety (PHP 8.1+). Replaces manual array-to-object hydration with a declarative, self-documenting approach.
  • Separation of Concerns: Encapsulates validation, casting, and transformation logic within the Describe attribute, reducing boilerplate in services/repositories.
  • Laravel Ecosystem Synergy:
    • Complements Laravel’s Illuminate\Support\Collection and Illuminate\Database\Eloquent\Model (e.g., for API responses or form requests).
    • Integrates with Laravel Validation (see Laravel Validation example in docs).
    • Works alongside existing packages like spatie/array-to-object but with stricter typing and fewer edge cases.

Integration Feasibility

  • Low Friction: Drop-in replacement for manual hydration (e.g., User::from($request->all())).
  • Backward Compatibility: Non-breaking; existing constructors remain functional (though from() is preferred).
  • Laravel-Specific Hooks: Can extend Describe to integrate with Laravel’s event system (e.g., pre/post hooks triggering ModelEvents).
  • ORM Integration: Potential to auto-hydrate Eloquent models from database arrays (via via or custom from() methods).

Technical Risk

  • Reflection Overhead: Attribute reflection adds minimal runtime cost (~10–20ms per hydration for complex objects), but may impact high-throughput APIs. Benchmark before production use.
  • Attribute Learning Curve: Developers unfamiliar with PHP 8+ attributes may resist adoption. Mitigate with:
    • Internal style guides mandating Describe for all DTOs.
    • Pair programming sessions to demonstrate ROI (e.g., fewer bugs in data flow).
  • Custom Logic Complexity: Overusing pre/post hooks or nested via calls can obfuscate data flow. Enforce simplicity via code reviews.
  • Testing Implications:
    • Unit tests must verify Describe configurations (e.g., required fields, casts).
    • Edge cases (e.g., recursive hydration failures) need explicit test coverage.

Key Questions

  1. Adoption Scope:
    • Will this replace all manual hydration (e.g., in API controllers) or only new DTOs?
    • How will we handle legacy codebases with deep array-to-object patterns?
  2. Performance:
    • Should we cache ReflectionAttribute instances for hot paths (e.g., API responses)?
    • Does this conflict with Laravel’s OPcache or JIT compilation?
  3. Tooling:
    • Can we integrate with Laravel’s php artisan make:model to auto-generate Describe attributes?
    • Should we build a custom Describe IDE plugin for VSCode/PhpStorm?
  4. Error Handling:
    • How will we surface PropertyRequiredException to API consumers (e.g., as HTTP 422 with validation-like errors)?
    • Should we extend Laravel’s Validator to reuse Describe rules?
  5. Long-Term Maintenance:
    • Will we need to fork this package to add Laravel-specific features (e.g., Eloquent model hydration)?
    • How will we handle breaking changes in the upstream library?

Integration Approach

Stack Fit

  • PHP 8.1+: Required for attributes and union types. Laravel 9+ (PHP 8.0+) may need polyfills or targeted upgrades.
  • Laravel Ecosystem:
    • APIs: Ideal for request DTOs (e.g., StoreUserRequest::from($request->all())).
    • Eloquent: Can hydrate models from database arrays (via custom via methods or base model traits).
    • Validation: Describe rules can map to Laravel’s Validator (e.g., requiredrequired|string).
    • Testing: Works with Pest/PHPUnit for type-safe test data generation.
  • Third-Party Packages:
    • Spatie Array-to-Object: Replace with DataModel for stricter typing.
    • Laravel Serializable: Use DataModel to define serialization rules declaratively.

Migration Path

  1. Pilot Phase:
    • Start with non-critical DTOs (e.g., API responses, form requests).
    • Example: Replace new User($request->input()) with User::from($request->all()).
  2. Incremental Rollout:
    • Phase 1: Add DataModel trait to new DTOs; keep existing constructors for backward compatibility.
    • Phase 2: Refactor services to use from() instead of manual hydration.
    • Phase 3: Deprecate legacy constructors (via @deprecated PHPDoc).
  3. Tooling Support:
    • Create a php artisan make:datamodel stub to auto-generate Describe attributes.
    • Build a DataModel IDE plugin to highlight missing/incorrect attributes.

Compatibility

  • Existing Code:
    • Non-breaking: Existing constructors remain functional.
    • Use #[Describe(['ignore'])] to exclude properties from from() hydration.
  • Laravel-Specific:
    • Form Requests: Extend Illuminate\Foundation\Http\FormRequest to use DataModel::from() for validation.
    • API Resources: Replace toArray() with Describe-driven serialization (via Transformable package).
    • Service Providers: Bind DataModel interfaces to concrete implementations.
  • Database:
    • Use via to hydrate Eloquent models from query results (e.g., User::from($user->toArray())).

Sequencing

  1. Core Integration:
    • Add zero-to-prod/data-model to composer.json.
    • Publish documentation via post-install-cmd (as shown in README).
  2. Developer Onboarding:
    • Train team on Describe attributes via workshops.
    • Create a DataModel style guide (e.g., "Always use required for non-nullable fields").
  3. Critical Path Refactoring:
    • Start with high-impact, low-risk areas (e.g., API request/response DTOs).
    • Example: Replace UserResource::toArray() with a UserResource class using DataModel for serialization.
  4. Testing:
    • Write integration tests for from() hydration in key workflows (e.g., user registration).
    • Add property-level tests for Describe configurations (e.g., "cast to uppercase").
  5. Monitoring:
    • Track hydration performance in production (e.g., from() execution time).
    • Monitor PropertyRequiredException rates to validate data quality.

Operational Impact

Maintenance

  • Pros:
    • Reduced Boilerplate: Describe attributes replace 5–10 lines of constructor logic per property.
    • Centralized Rules: Validation/casting logic lives with property declarations (easy to find/change).
    • Type Safety: IDE autocompletion and static analysis catch errors early.
  • Cons:
    • Attribute Bloat: Overuse of Describe can make classes verbose. Mitigate with:
      • Shared Describe configurations (e.g., base traits for common casts).
      • IDE collapse/expand for attributes.
    • Reflection Dependencies: Attribute parsing may complicate future PHP upgrades (e.g., if reflection APIs change).

Support

  • Developer Experience:
    • Onboarding: Requires understanding of PHP attributes and resolution order. Provide:
      • Cheat sheets for Describe keys.
      • Example repositories with common patterns (e.g., nested hydration, Laravel integration).
    • Debugging: Errors like PropertyRequiredException need clear documentation on how to:
      • Handle missing fields in APIs (e.g., return 422 with field names).
      • Log hydration failures for observability.
  • Error Handling:
    • Customize exception messages for API consumers (e.g., translate PropertyRequiredException to JSON:API errors).
    • Example:
      catch (PropertyRequiredException $e) {
          return response()->json([
              'errors' => [['field' => $e->getProperty(), 'message' => $e->getMessage()]]
          ], 422);
      }
      

Scaling

  • Performance:
    • Benchmark: Test hydration time for 100+ properties. Optimize with:
      • Caching ReflectionAttribute instances for static properties.
      • Lazy-loading Describe attributes (e.g., only parse when from() is called).
    • High Load: For APIs, consider:
      • Pre-compiling Describe configurations (e.g., serialize to JSON at boot).
      • Using via to batch-hydrate collections (e.g., User::fromMany($array)).
  • Database:
    • Eloquent: Use via to hydrate models from query results without N+1 queries:
      class User extends Model {
          use DataModel;
          #[Describe(['via' => [
      
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
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
twbs/bootstrap4
php-http/client-implementation
phpcr/phpcr-implementation
cucumber/gherkin-monorepo
haydenpierce/class-finder
psr/simple-cache-implementation