Computed Properties
Learn how to calculate values on-the-fly using computed properties.
What are Computed Properties?
Section titled “What are Computed Properties?”Computed properties are methods that calculate values based on other properties and are automatically included in serialization:
class UserDTO extends SimpleDTO{ public function __construct( public readonly string $firstName, public readonly string $lastName, ) {}
#[Computed] public function fullName(): string { return $this->firstName . ' ' . $this->lastName; }}
$dto = new UserDTO(firstName: 'John', lastName: 'Doe');echo $dto->fullName(); // John Doe
$array = $dto->toArray();// ['firstName' => 'John', 'lastName' => 'Doe', 'fullName' => 'John Doe']Basic Usage
Section titled “Basic Usage”Using #[Computed] Attribute
Section titled “Using #[Computed] Attribute”use Event4u\DataHelpers\SimpleDTO\Attributes\Computed;
class ProductDTO extends SimpleDTO{ public function __construct( public readonly float $price, public readonly float $taxRate, ) {}
#[Computed] public function priceWithTax(): float { return $this->price * (1 + $this->taxRate); }
#[Computed] public function taxAmount(): float { return $this->price * $this->taxRate; }}
$dto = new ProductDTO(price: 100, taxRate: 0.19);echo $dto->priceWithTax(); // 119.0echo $dto->taxAmount(); // 19.0Real-World Examples
Section titled “Real-World Examples”User Profile
Section titled “User Profile”class UserDTO extends SimpleDTO{ public function __construct( public readonly string $firstName, public readonly string $lastName, public readonly string $email, public readonly Carbon $birthDate, ) {}
#[Computed] public function fullName(): string { return "{$this->firstName} {$this->lastName}"; }
#[Computed] public function age(): int { return $this->birthDate->age; }
#[Computed] public function initials(): string { return strtoupper($this->firstName[0] . $this->lastName[0]); }}Order Calculations
Section titled “Order Calculations”class OrderDTO extends SimpleDTO{ public function __construct( public readonly float $subtotal, public readonly float $taxRate, public readonly float $shippingCost, public readonly float $discount, ) {}
#[Computed] public function taxAmount(): float { return $this->subtotal * $this->taxRate; }
#[Computed] public function total(): float { return $this->subtotal + $this->taxAmount() + $this->shippingCost - $this->discount; }
#[Computed] public function savings(): float { return $this->discount; }}Combining with Other Features
Section titled “Combining with Other Features”Computed + Conditional
Section titled “Computed + Conditional”class UserDTO extends SimpleDTO{ public function __construct( public readonly string $firstName, public readonly string $lastName, ) {}
#[Computed] #[WhenAuth] public function fullName(): string { return $this->firstName . ' ' . $this->lastName; }}Computed + Lazy
Section titled “Computed + Lazy”class UserDTO extends SimpleDTO{ public function __construct( public readonly int $userId, ) {}
#[Computed] #[Lazy] public function statistics(): array { return [ 'posts' => Post::where('user_id', $this->userId)->count(), 'comments' => Comment::where('user_id', $this->userId)->count(), ]; }}Computed + Hidden
Section titled “Computed + Hidden”class UserDTO extends SimpleDTO{ public function __construct( public readonly string $firstName, public readonly string $lastName, ) {}
#[Computed] #[Hidden] public function internalId(): string { return md5($this->firstName . $this->lastName); }}
$array = $dto->toArray();// ['firstName' => 'John', 'lastName' => 'Doe']// internalId is excludedBest Practices
Section titled “Best Practices”Keep Computations Simple
Section titled “Keep Computations Simple”// ✅ Good - simple calculation#[Computed]public function fullName(): string{ return $this->firstName . ' ' . $this->lastName;}
// ❌ Bad - complex logic#[Computed]public function complexCalculation(): array{ // 100 lines of complex logic}Use Type Hints
Section titled “Use Type Hints”// ✅ Good - with type hint#[Computed]public function total(): float{ return $this->price * $this->quantity;}
// ❌ Bad - no type hint#[Computed]public function total(){ return $this->price * $this->quantity;}Cache Expensive Computations
Section titled “Cache Expensive Computations”class UserDTO extends SimpleDTO{ private ?array $cachedStats = null;
#[Computed] #[Lazy] public function statistics(): array { if ($this->cachedStats === null) { $this->cachedStats = [ 'posts' => Post::where('user_id', $this->userId)->count(), 'comments' => Comment::where('user_id', $this->userId)->count(), ]; }
return $this->cachedStats; }}Code Examples
Section titled “Code Examples”The following working examples demonstrate this feature:
- Basic Computed - Simple computed properties
All examples are fully tested and can be run directly.
Related Tests
Section titled “Related Tests”The functionality is thoroughly tested. Key test files:
- ComputedPropertiesTest.php - Computed property tests
Run the tests:
# Run teststask test:unit -- --filter=ComputedSee Also
Section titled “See Also”- Lazy Properties - Defer expensive operations
- Conditional Properties - Dynamic visibility
- Type Casting - Automatic type conversion