Weave 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

Value Object Contracts Laravel Package

boson-php/value-object-contracts

View on GitHub
Deep Wiki
Context7

Getting Started

Minimal Setup

  1. Installation

    composer require boson-php/value-object-contracts
    

    No additional configuration is needed—this is a contract-only package.

  2. First Use Case: Defining a Value Object Create a class implementing Boson\ValueObject\ValueObjectContract:

    use Boson\ValueObject\ValueObjectContract;
    
    class Email implements ValueObjectContract
    {
        private string $value;
    
        public function __construct(string $value)
        {
            $this->value = $value;
        }
    
        public function equals(ValueObjectContract $other): bool
        {
            return $this->value === $other->getValue();
        }
    
        public function getValue(): string
        {
            return $this->value;
        }
    }
    
  3. Where to Look First

    • Contracts: Browse Boson\ValueObject\ namespace for core interfaces.
    • Documentation: Check the Boson framework docs (parent project) for patterns.
    • Tests: Study tests/ for real-world usage examples.

Implementation Patterns

1. Value Object Composition

Use ValueObjectContract for immutable, self-validating objects:

class UserId implements ValueObjectContract
{
    private string $id;

    public function __construct(string $id)
    {
        if (!preg_match('/^[a-f0-9]{24}$/', $id)) {
            throw new \InvalidArgumentException('Invalid ID format');
        }
        $this->id = $id;
    }

    public function equals(ValueObjectContract $other): bool
    {
        return $this->id === $other->getValue();
    }

    public function getValue(): string
    {
        return $this->id;
    }
}

2. Integration with Laravel

  • Form Requests: Validate inputs as Value Objects:
    use Boson\ValueObject\ValueObjectContract;
    
    class StoreUserRequest extends FormRequest
    {
        public function validate(): array
        {
            return [
                'email' => ['required', 'email'],
            ];
        }
    
        public function validatedValueObjects(): array
        {
            return [
                'email' => new Email($this->input('email')),
            ];
        }
    }
    
  • Eloquent Models: Store Value Objects in attributes:
    class User extends Model
    {
        protected $casts = [
            'email' => Email::class,
        ];
    }
    

3. Collections of Value Objects

Use Boson\ValueObject\Collection for typed collections:

use Boson\ValueObject\Collection;

$emails = Collection::make([
    new Email('[email protected]'),
    new Email('[email protected]'),
]);

4. Domain-Driven Design (DDD)

  • Entities vs. Value Objects: Use ValueObjectContract for objects like Email, Money, or DateRange.
  • Repositories: Store Value Objects in databases as strings/JSON and hydrate them on retrieval.

Gotchas and Tips

Pitfalls

  1. Immutability

    • Value Objects must be immutable. Avoid setters or mutable properties.
    • Fix: Use constructor injection and private properties.
  2. Equality Contracts

    • equals() must be consistent with ==. For example:
      // Bad: Compares object references
      public function equals(ValueObjectContract $other): bool {
          return $this === $other;
      }
      
    • Fix: Compare internal values (e.g., $this->value === $other->getValue()).
  3. Database Storage

    • Laravel’s $casts may not work out-of-the-box for complex Value Objects.
    • Fix: Use accessors/mutators or serialize manually:
      protected $attributes = ['email' => null];
      
      public function getEmailAttribute($value)
      {
          return $value ? new Email($value) : null;
      }
      
      public function setEmailAttribute($value)
      {
          $this->attributes['email'] = $value instanceof Email ? $value->getValue() : $value;
      }
      
  4. Performance with Large Collections

    • Collection::equals() performs O(n) comparisons. Avoid in hot paths.
    • Fix: Use a HashSet-like structure for lookups if needed.

Debugging Tips

  • Type Safety: Use instanceof ValueObjectContract to verify objects.
  • Serialization: Implement __toString() for debugging:
    public function __toString(): string
    {
        return $this->getValue();
    }
    
  • Testing: Mock equals() in unit tests to verify behavior:
    $this->assertTrue((new Email('[email protected]'))->equals(new Email('[email protected]')));
    

Extension Points

  1. Custom Validation Extend ValueObjectContract with validation logic in the constructor:

    class Age implements ValueObjectContract
    {
        private int $value;
    
        public function __construct(int $value)
        {
            if ($value < 0 || $value > 120) {
                throw new \InvalidArgumentException('Invalid age');
            }
            $this->value = $value;
        }
        // ... equals(), getValue()
    }
    
  2. JSON Serialization Implement JsonSerializable for API responses:

    use JsonSerializable;
    
    class Money implements ValueObjectContract, JsonSerializable
    {
        // ...
        public function jsonSerialize(): array
        {
            return ['amount' => $this->amount, 'currency' => $this->currency];
        }
    }
    
  3. Laravel Service Providers Bind Value Objects to the container for dependency injection:

    $this->app->bind(Email::class, function ($app) {
        return new Email($app['request']->input('email'));
    });
    
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.
elmogy/larafast
xeviant/laravel-paystack
gorilladash/laravel-website-sdk
martialbe/flysystem-oss
chondal/3312client
jeroen-g/flickr
opscale-co/nova-genbi
itsjustvita/laravel-retention
tequilarapido/trackit
gregsphotography/site-builder-filament
cabaoctavio/laravel-query-log
gregsphotography/site-builder-components
io-digital/clickatell
snowsoft/laravel-admin
oxygen/auth
relicsoftware/barakah-payment-gateway
tobya/work-with-composer
equipc/laravel-email-validator
equipc/laravel-email-database-log
adedsec/nova-translated-labels