Installation Add the package via Composer:
composer require apie/text-value-objects
Ensure your Laravel project meets the package's PHP version requirements (check composer.json for constraints).
First Use Case
Import the base TextValueObject class and extend it for domain-specific text values:
use Apie\TextValueObjects\TextValueObject;
class EmailAddress extends TextValueObject
{
public function __construct(string $value)
{
parent::__construct($value);
}
public function validate(): void
{
if (!filter_var($this->value, FILTER_VALIDATE_EMAIL)) {
throw new \InvalidArgumentException('Invalid email format.');
}
}
}
Use it in a Laravel model or DTO:
$email = new EmailAddress('user@example.com');
Domain-Specific Text Validation
Extend TextValueObject to enforce business rules:
class Username extends TextValueObject
{
public function validate(): void
{
if (strlen($this->value) < 3) {
throw new \InvalidArgumentException('Username must be at least 3 characters.');
}
}
}
Integration with Laravel Models
Use accessors/mutators to convert between plain strings and TextValueObject instances:
class User extends Model
{
protected $casts = [
'email' => EmailAddress::class,
];
public function setEmailAttribute(string $value)
{
$this->attributes['email'] = new EmailAddress($value);
}
public function getEmailAttribute(EmailAddress $value)
{
return $value->value;
}
}
API Request Validation
Validate incoming requests using Laravel's FormRequest:
use Apie\TextValueObjects\TextValueObject;
class StoreUserRequest extends FormRequest
{
public function validate()
{
return [
'email' => ['required', function ($attribute, $value, $fail) {
try {
new EmailAddress($value);
} catch (\InvalidArgumentException $e) {
$fail($e->getMessage());
}
}],
];
}
}
Serialization/Deserialization Use Laravel's JSON serialization or custom logic:
$serialized = json_encode(['email' => $user->email->value]);
$deserialized = new EmailAddress(json_decode($serialized, true)['email']);
Validation Timing
validate() is called only during instantiation. Reuse objects carefully:
$email = new EmailAddress('test@example.com'); // Validated once
$email->value = 'invalid'; // No re-validation!
revalidate() method or use immutable objects.Type Safety
string input. Explicitly type-hint constructors:
public function __construct(string $value) { ... }
Laravel Caching Quirks
TextValueObject instances may not cache correctly. Use value property explicitly:
Cache::put('key', $user->email->value);
Override __toString() for debugging:
public function __toString(): string
{
return sprintf('(%s: %s)', static::class, $this->value);
}
Custom Exceptions Extend validation errors with domain-specific messages:
throw new \InvalidArgumentException('Username must be alphanumeric.');
Add Metadata
Store additional attributes (e.g., createdAt):
class Tag extends TextValueObject
{
public function __construct(string $value, public \DateTime $createdAt)
{
parent::__construct($value);
}
}
Localization Internationalize validation messages:
public function validate(): void
{
if (!preg_match('/^[a-z]+$/', $this->value)) {
throw new \InvalidArgumentException(__('Validation.custom.alphabetic'));
}
}
Immutable Design Prevent value modification after creation:
private function __set(string $name, $value): void
{
throw new \RuntimeException('Immutable object.');
}
How can I help you explore Laravel packages today?