georgii-web / php-typed-values
Typed value objects library for common php data types.
Installs: 209
Dependents: 0
Suggesters: 0
Security: 0
Stars: 1
Watchers: 1
Forks: 0
Open Issues: 0
pkg:composer/georgii-web/php-typed-values
Requires
- php: >=8.2
Requires (Dev)
- friendsofphp/php-cs-fixer: ^v3.89
- pestphp/pest: ^v3.8.4
- pestphp/pest-plugin-type-coverage: ^v3.6
- phpunit/phpunit: ^11.5
- rector/rector: ^2.2
- vimeo/psalm: ^6.13.1
- dev-master
- v2.8.1
- v2.8.0
- v2.7.7
- v2.7.6
- v2.7.5
- v2.7.4
- v2.7.3
- v2.7.2
- v2.7.1
- v2.7.0
- v2.6.17
- v2.6.16
- v2.6.15
- v2.6.14
- v2.6.13
- v2.6.12
- v2.6.11
- v2.6.10
- v2.6.9
- v2.6.8
- v2.6.7
- v2.6.6
- v2.6.5
- v1.8.1
- v1.8.0
- v1.7.7
- v1.7.6
- v1.7.5
- v1.7.4
- v1.7.2
- v1.7.1
- v1.7.0
- v1.6.17
- v1.6.16
- v1.6.15
- v1.6.14
- v1.6.13
- v1.6.12
- v1.6.11
- v1.6.10
- v1.6.9
- v1.6.8
- v1.6.7
- v1.6.4
- v1.6.3
- v1.6.2
- v1.6.1
- v1.6.0
- v1.5.2
- v1.5.1
- v1.5.0
- v1.4.1
- v1.4.0
- v1.3.1
- v1.3.0
- v1.2.0
- v1.1.0
- 1.0.0
- dev-php7.4
This package is auto-updated.
Last update: 2025-12-14 22:48:31 UTC
README
PHP Typed Values
Typed value objects for PHP. Build precise, immutable, and validated data for DTOs, Value Objects, and Entities.
Install
- Use V2 for PHP 8.2+:
composer require georgii-web/php-typed-values:^2
- Use V1 for PHP 7.4:
composer require georgii-web/php-typed-values:^1
Why
- Strong typing for scalars with runtime validation
- Immutable and self‑documenting values
- Safer constructors for your DTOs/VOs/Entities
- Great fit for static analysis (Psalm/PHPStan)
Quick start
Use existing typed values
use TypedValues\Integer\IntegerPositive; $id = IntegerPositive::fromString('123');
Instead of spreading validation across an application
$id = (int) '123'; if ($id <= 0) { throw new InvalidArgumentException('Invalid ID'); }
Create an alias (domain name)
use TypedValues\Integer\IntegerPositive; readonly class Id extends IntegerPositive {} Id::fromInt(123);
Compose value objects
use TypedValues\Integer\IntegerPositive; use TypedValues\String\StringNonEmpty; use TypedValues\Float\FloatPositive; use TypedValues\Undefined\Alias\Undefined; // represents an intentionally missing value final readonly class Profile { public function __construct( private IntegerPositive $id, private StringNonEmpty|Undefined $firstName, private FloatPositive|Undefined $height, ) {} public static function fromScalars( int $id, ?string $firstName, string|float|int|null $height = null, ): self { return new self( IntegerPositive::fromInt($id), // early fail (must be valid) StringNonEmpty::tryFromMixed($firstName), // late fail (maybe undefined) $height !== null ? FloatPositive::fromString((string) $height) // early fail if provided : Undefined::create(), // late fail when accessed ); } public function getFirstName(): StringNonEmpty|Undefined { return $this->firstName; } public function getHeight(): FloatPositive|Undefined { return $this->height; } }
Early fail (invalid input prevents creation)
Profile::fromScalars(id: 0, firstName: 'Alice', height: '172.5'); // throws exception
Late fail with Undefined (an object exists, fail on access)
$profile = Profile::fromScalars(id: 101, firstName: '', height: '172.5'); // created $profile->getFirstName()->value(); // throws an exception on access the Undefined value
Optional fail (only fail if the optional value is provided and invalid)
Ideal for partial data handling (e.g., requests where only specific fields, like ID, are required), allowing access to valid fields without failing on missing ones.
Profile::fromScalars(id: 101, firstName: 'Alice', height: -1); // invalid provided value -> early fail $profile = Profile::fromScalars(id: 101, firstName: 'Alice', height: null); // value omitted -> created, fails only on access $profile->getHeight()->value(); // throws an exception on access the Undefined value
Key features
- Static analysis friendly (Psalm/PHPStan-ready types)
- Strict types with
declare(strict_types=1); - Validation on construction; no invalid state
- Immutable, readonly objects
- No external runtime dependencies
- Easy to extend with your own types and composites
Performance note
- Objects vs scalars:
- ~3× slower for large arrays of objects
- ~2× higher memory usage
- Use value objects for domain boundaries, validation, and clarity
- Use raw scalars in hot loops or large data processing paths
Documentation
- Development guide:
docs/DEVELOP.md - Usage examples in
src/Usageandtests/Unit
License
MIT