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

Self Aware Normalizers Laravel Package

digital-craftsman/self-aware-normalizers

View on GitHub
Deep Wiki
Context7

Technical Evaluation

Architecture Fit

  • Domain-Driven Design (DDD) Alignment: The package aligns well with DDD principles, particularly the use of Value Objects (VOs) and DTOs that encapsulate their own serialization logic. This reduces coupling between domain logic and infrastructure (e.g., API responses, database storage).
  • Symfony Ecosystem: Designed as a Symfony bundle, it integrates seamlessly with Symfony’s Serializer Component, making it ideal for Laravel applications using Symfony’s Serializer (via symfony/serializer or nesbot/carbon for Laravel).
  • Self-Contained Logic: Encapsulating normalization/denormalization within VOs/DTOs improves cohesion and maintainability by keeping data structure and serialization logic co-located.

Integration Feasibility

  • Laravel Compatibility:
    • Requires PHP 8.4/8.5 (Laravel 10+ supports this).
    • Can be integrated via Symfony’s Serializer (if already in use) or Laravel’s built-in JSON responses (with custom normalizers).
    • No native Laravel support, but the package’s interfaces (Normalizable, Denormalizable) can be manually implemented in Laravel’s VOs/DTOs.
  • Existing Serialization Stack:
    • If using Fractal, Laravel’s toArray(), or custom JSON responses, this package may require additional adapters (e.g., wrapping normalizers).
    • If using Symfony’s Serializer, integration is straightforward (minimal boilerplate).

Technical Risk

  • Breaking Changes: The package is new (2026) with no dependents, so long-term stability is unproven. Risk of API changes in minor versions.
  • Performance Overhead:
    • Self-normalizing VOs add indirection (e.g., VO::normalize() calls instead of direct property access).
    • May impact serialization speed in high-throughput APIs (benchmark before adoption).
  • Design Trade-offs:
    • Anemic vs. Rich Domain Models: Self-aware VOs shift logic from serializers to domain objects, which some may argue violates separation of concerns.
    • Testing Complexity: Mutation testing suggests robustness, but Laravel’s testing stack (Pest/PHPUnit) may need adjustments for VO-specific assertions.

Key Questions

  1. Does the team already use Symfony’s Serializer or a competing library (Fractal, Spatie Arrayable)?
    • If not, what’s the cost of adopting it vs. building custom normalizers?
  2. How critical is serialization performance?
    • Benchmark against current toArray()/Arrayable implementations.
  3. Will this introduce circular references in VOs?
    • The package doesn’t explicitly handle circular references (common in DTOs).
  4. How will this interact with Laravel’s API Resources or Eloquent models?
    • May require hybrid approaches (e.g., VOs for domain logic, Resources for API responses).
  5. Is the team comfortable with VO-centric design?
    • Requires buy-in for rich domain models over anemic DTOs.

Integration Approach

Stack Fit

Laravel Component Integration Strategy
Symfony Serializer Direct integration via digital-craftsman/self-aware-normalizers.
Laravel JSON Responses Use package’s normalizers as custom JSON encoders (via Illuminate\Contracts\Json).
Fractal/Arrayable Wrap VOs in custom transformers that delegate to Normalizable::normalize().
Eloquent Models Use VOs for domain logic, serialize via App\ValueObjects\Email::normalize().
API Resources Extend JsonResource to use VO normalizers (e.g., $resource->mergeWhen($vo->normalize())).

Migration Path

  1. Phase 1: Pilot with Non-Critical VOs
    • Start with 1-2 VOs (e.g., Email, Money) to test integration.
    • Compare serialization output with current toArray().
  2. Phase 2: Adapter Layer (If Needed)
    • If not using Symfony Serializer, build a thin adapter to bridge Laravel’s JSON responses:
      // app/Normalizers/ValueObjectNormalizer.php
      use DigitalCraftsman\SelfAwareNormalizers\Normalizable;
      
      class ValueObjectNormalizer implements \Symfony\Component\Serializer\Normalizer\NormalizerInterface {
          public function normalize($object, string $format = null, array $context = []): array {
              return $object instanceof Normalizable ? $object->normalize() : (array)$object;
          }
      }
      
  3. Phase 3: Full Adoption
    • Replace Arrayable/toArray() with Normalizable for all VOs.
    • Update API contracts (OpenAPI/Swagger) to reflect new structures.

Compatibility

  • PHP 8.4/8.5: Laravel 10+ supports this; downgrade not recommended.
  • Symfony Serializer: Required for full feature set. If using Laravel’s native JSON, partial compatibility is possible.
  • Existing Normalizers: May conflict if using custom Serializer configurations. Audit existing normalizers before integration.
  • Caching: If using Symfony’s Serializer with caching, ensure VO normalizers are cacheable (they should be stateless).

Sequencing

  1. Add Dependency:
    composer require digital-craftsman/self-aware-normalizers
    
  2. Implement Interfaces:
    use DigitalCraftsman\SelfAwareNormalizers\Normalizable;
    use DigitalCraftsman\SelfAwareNormalizers\Denormalizable;
    
    class Email implements Normalizable, Denormalizable {
        public function normalize(): array {
            return ['address' => $this->address, 'verified' => $this->verified];
        }
    
        public static function denormalize(array $data): self {
            return new self($data['address'], $data['verified'] ?? false);
        }
    }
    
  3. Configure Serializer (Symfony):
    # config/services.yaml (if using Symfony)
    framework:
        serializer:
            mappings:
                - namespace: App\ValueObjects
                  resource: '../src/ValueObjects'
                - namespace: DigitalCraftsman\SelfAwareNormalizers
                  resource: '@digital-craftsman/self-aware-normalizers'
    
  4. Update Controllers/Resources:
    • Replace return $vo->toArray() with return $this->serializer->normalize($vo).
    • For API Resources, use $resource->additional(['vo_data' => $vo->normalize()]).

Operational Impact

Maintenance

  • Pros:
    • Reduced boilerplate: No need for separate serializers/transformers for VOs.
    • Single source of truth: Data structure and serialization logic co-located in VOs.
    • Easier refactoring: Changing a VO’s structure automatically updates its serialization.
  • Cons:
    • VO bloat: Normalization logic in domain objects may violate SRP for some teams.
    • Testing overhead: Need to test both domain logic and serialization for VOs.
    • Dependency on package: Future changes to the package may require VO updates.

Support

  • Debugging:
    • Harder to trace: Serialization errors may surface as VO-specific exceptions (e.g., invalid denormalization).
    • Tooling gaps: Laravel’s dd() or dump() won’t show normalized form; may need custom helpers.
  • Documentation:
    • Limited ecosystem: No Laravel-specific guides; rely on Symfony docs.
    • Team onboarding: Requires training on VO patterns and new interfaces.
  • Vendor Support:
    • No official support: MIT license means community-driven fixes.

Scaling

  • Performance:
    • Cold start impact: Self-normalizing VOs add reflection/indirection (measure with microtime).
    • Caching: If using Symfony Serializer, enable caching for normalized VOs:
      framework:
          serializer:
              cache:
                  pools:
                      app.cache.pool
      
  • Horizontal Scaling:
    • Stateless: No shared state in VOs; scales well in queue workers/APIs.
    • Database: If VOs are stored as JSON, ensure DB supports efficient JSON queries (PostgreSQL > MySQL).
  • Team Scaling:
    • Consistent patterns: Reduces serialization bugs as team grows.
    • Specialization risk: May require dedicated VO maintainers for complex logic.

Failure Modes

| Failure Scenario | Impact | **

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