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

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('user1@example.com'),
    new Email('user2@example.com'),
]);

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('test@example.com'))->equals(new Email('test@example.com')));
    

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.
terminal42/code-quality-tools
codifyo/ts-generator-bundle
andydefer/laravel-cluster
testo/fiber
mintobit/jobqueue
a4sex/maintenance-bundle
a4sex/entity-date-update
a4sex/client-identifier
a4sex/base-utilites
a4sex/key-value-storage
a4sex/micro-status
chilldev/dependency-injection-extra
datinglibre/datinglibre-app-api
biberltd/corebundle
bricre/symfony-bundle-test
biberltd/logbundle
dominium/http-adapter-bundle
dominium/google-analytics
a4sex/auto-clean-entity
christhompsontldr/laravel-inky