Skip to content

Computed Properties

Learn how to calculate values on-the-fly using 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']
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.0
echo $dto->taxAmount(); // 19.0
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]);
}
}
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;
}
}
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;
}
}
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(),
];
}
}
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 excluded
// ✅ 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
}
// ✅ 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;
}
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;
}
}

The following working examples demonstrate this feature:

All examples are fully tested and can be run directly.

The functionality is thoroughly tested. Key test files:

Run the tests:

Terminal window
# Run tests
task test:unit -- --filter=Computed