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

Valueobjects Laravel Package

cubicmushroom/valueobjects

A small PHP package providing lightweight Value Object classes to model immutable domain values (e.g., IDs, money, email, dates) with validation and type-safety. Useful for cleaner Laravel apps and DDD-style codebases.

View on GitHub
Deep Wiki
Context7

Getting Started

Minimal Setup

  1. Installation

    composer require cubicmushroom/valueobjects
    

    Add to composer.json if not auto-loaded:

    "autoload": {
        "psr-4": {
            "App\\": "app/",
            "CubicMushroom\\ValueObjects\\": "vendor/cubicmushroom/valueobjects/src/"
        }
    }
    

    Run composer dump-autoload.

  2. First Use Case Define a simple value object (e.g., Email):

    use CubicMushroom\ValueObjects\AbstractValueObject;
    
    class Email extends AbstractValueObject
    {
        protected $value;
    
        public function __construct(string $value)
        {
            $this->value = $value;
        }
    
        public function getValue(): string
        {
            return $this->value;
        }
    
        public function __toString(): string
        {
            return $this->value;
        }
    }
    
  3. Key Features to Explore

    • Immutable by default: Values cannot be changed after creation.
    • Equality comparison: Uses value for comparison, not object identity.
    • Type safety: Enforce strict typing in constructors.

Implementation Patterns

Workflows

  1. Domain Modeling Use value objects for:

    • Simple entities (e.g., Money, Email, Username).
    • Immutable state (e.g., OrderId, ProductSku). Example:
    class Money extends AbstractValueObject
    {
        public function __construct(
            private float $amount,
            private string $currency
        ) {}
    
        public function add(Money $other): self
        {
            if ($this->currency !== $other->currency) {
                throw new \InvalidArgumentException("Currencies must match");
            }
            return new self($this->amount + $other->amount, $this->currency);
        }
    }
    
  2. Validation Override isValid() for custom rules:

    class Email extends AbstractValueObject
    {
        public function isValid(): bool
        {
            return filter_var($this->value, FILTER_VALIDATE_EMAIL) !== false;
        }
    }
    
  3. Integration with Eloquent Store value objects as JSON in a database column:

    use Illuminate\Database\Eloquent\Casts\Attribute;
    
    class User extends Model
    {
        protected function email(): Attribute
        {
            return Attribute::make(
                get: fn ($value) => new Email($value),
                set: fn ($value) => $value->getValue(),
            );
        }
    }
    
  4. Collections Use ValueObjectCollection for grouped value objects:

    use CubicMushroom\ValueObjects\ValueObjectCollection;
    
    $emails = new ValueObjectCollection([
        new Email('user1@example.com'),
        new Email('user2@example.com'),
    ]);
    

Best Practices

  • Naming: Prefix value objects with nouns (e.g., Email, Money).
  • Constructor Injection: Prefer dependency injection over setters.
  • Laravel Services: Use value objects in service classes for pure logic.

Gotchas and Tips

Pitfalls

  1. Serialization Issues

    • Value objects may not serialize/deserialize cleanly by default.
    • Fix: Implement __serialize()/__unserialize() or use JsonSerializable.
    class Email implements JsonSerializable
    {
        public function jsonSerialize(): string
        {
            return $this->value;
        }
    }
    
  2. Database Storage

    • Storing value objects directly in databases (without casting) may fail.
    • Tip: Use Laravel’s Attribute casting or serialize manually.
  3. Performance Overhead

    • Equality checks compare values, not object references. This can slow down collections.
    • Mitigation: Cache hash values if performance is critical.
  4. Magic Methods

    • Avoid __get()/__set() to maintain immutability. Use explicit getters/setters.

Debugging

  • Equality Confusion:
    $email1 = new Email('test@example.com');
    $email2 = new Email('test@example.com');
    var_dump($email1 == $email2); // true (values compared)
    var_dump($email1 === $email2); // false (object identity)
    
  • Validation Errors: Check isValid() returns false and inspect the value object’s logic.

Extension Points

  1. Custom Comparison Override equals() for complex logic:

    public function equals(AbstractValueObject $other): bool
    {
        return $this->value === $other->value;
    }
    
  2. Value Object Factories Create static factory methods for complex creation:

    class Money
    {
        public static function fromString(string $value): self
        {
            [$amount, $currency] = explode(' ', $value);
            return new self((float)$amount, $currency);
        }
    }
    
  3. Laravel Integration

    • Requests: Use value objects in form requests:
      public function rules(): array
      {
          return [
              'email' => ['required', 'string'],
          ];
      }
      
      public function prepareForValidation()
      {
          $this->merge([
              'email' => new Email($this->email),
          ]);
      }
      
    • API Responses: Transform value objects in toArray():
      public function toArray(): array
      {
          return [
              'email' => $this->email->getValue(),
          ];
      }
      
  4. Testing

    • Mock value objects for unit tests:
      $this->partialMock(Email::class, ['isValid'])
           ->shouldReceive('isValid')
           ->once()
           ->andReturn(true);
      
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.
cocosmos/filament-sticky-save-bar
patrickbussmann/oauth2-apple
3brs/enterprise-security-bundle
anousss007/vigilance
supportpal/eloquent-model
ardenexal/fhir-models
laravel-at/laravel-image-sanitize
romalytar/yammi-audit-log-laravel
ardenexal/fhir-validation
arshaviras/weather-widget
laravel-chronicle/core
sunchayn/nimbus
daikazu/eloquent-salesforce-objects
unseen-codes/chat
romalytar/yammi-jobs-monitoring-laravel
kisame76/filament-db-table-state
nqxcode/laravel-lucene-search
dpfx/laravel-livewire-wizards
workos/workos-php-laravel
sofa/laravel-global-scope