PHPackages                             webgraphe/phlux - PHPackages - PHPackages  [Skip to content](#main-content)[PHPackages](/)[Directory](/)[Categories](/categories)[Trending](/trending)[Leaderboard](/leaderboard)[Changelog](/changelog)[Analyze](/analyze)[Collections](/collections)[Log in](/login)[Sign up](/register)

1. [Directory](/)
2. /
3. [Utility &amp; Helpers](/categories/utility)
4. /
5. webgraphe/phlux

ActiveLibrary[Utility &amp; Helpers](/categories/utility)

webgraphe/phlux
===============

Yet another PHP DataTransferObject library

v0.4.0(3mo ago)03MITPHPPHP ^8.4

Since Jul 30Pushed 2mo ago1 watchersCompare

[ Source](https://github.com/webgraphe/phlux)[ Packagist](https://packagist.org/packages/webgraphe/phlux)[ RSS](/packages/webgraphe-phlux/feed)WikiDiscussions main Synced 1mo ago

READMEChangelog (4)Dependencies (3)Versions (7)Used By (0)

Yet Another PHP Data Transfer Object Library
============================================

[](#yet-another-php-data-transfer-object-library)

A DTO (Data Transfer Object) is a simple object holding data to be moved between different subsystems or layers of an application. They typically only contain public fields, constructors and getters. Therefore, a DTO:

- MUST be easy to understand
- MUST present and allow data transport in the simplest way
- SHOULD not contain business logic
- SHOULD be immutable, *i.e.* its state should not change after it is created

This is Phlux.

Declaration
-----------

[](#declaration)

A Phlux DTO is strictly declared using PHP language constructs; there is **no magic**.

The bare minimum to make a class into a DTO is to extend the `readonly` class `Data` which implements `DataTransferObject`, inheriting `JsonSerializable` and `IteratorAggregate` in the process.

Important

While not guaranteed to be immutable, a `readonly` class ensures instances cannot be tampered with after initialization, albeit with some caveats:

- A DTO cannot have `static` properties
- All properties MUST be typed
- It's still possible to initialize an uninitialized property after construction (albeit in a `protected(set)` manner)

Supported property types range from:

- Scalars (`int`, `float`, `string`, `bool`)
- Composites (`array`, `object`)
- `null`
- Anything extending `Data`
- `DateTimeInterface`, `DateTimeImmutable` and `BackedEnum`

`array` properties are always hydrated as `0`-based lists. `object` properties are always hydrated as a key-value map instances of `stdClass`. Without attributes, composites can store arbitrary data.

A composite property may narrow the type(s) of items it contains with the `#[ItemType]` attribute, passing a `class-string` or the name of any aforementioned supported types above.

An `#[ItemPrototype]` attribute may be declared with the name of another property of the same class to be used as the prototype of the collection's item (non-`public` properties can used as prototype for that effect).

All properties can be nullable by either prefixing the type name with a question mark or declaring a union with `null`.

When the data for a property is missing from a payload, unless a `#[Present]` attribute is found on the property (indicating to skip initialization), a default value is assigned:

- `null` when nullable
- `0` for `int`
- `0.0` for `float`
- `false` for `bool`
- `''` for `string`
- `[]` for `array`
- `new stdClass()` for `object`
- Current time for anything implementing `DateTimeInterface` and anything extending `DateTimeImmutable`
- The first `BackedEnum::cases()` item for `enum`
- A new instance with `null` payload for anything implementing `DataTransferObject`

Note

Uninitialized properties are not serialized.

Adding the `#[Discriminator]` attribute on a `DataTransferObject` class (MUST be `abstract`) allows for inheritance and polymorphism of DTOs and their properties to hydrate. It must be given the name of a `final`, non-nullable `string` property on the attributed class containing the discriminator value which can be matched against a given mapping or composed with the namespace of the discriminated DTO.

There is no support (yet) for Union or Intersection properties, except unions with `null`.

Presentation and transportation are handled for all `public` properties (non-`public` properties may be defined but are not serialized).

Instantiation
-------------

[](#instantiation)

DTOs may be hydrated in different ways:

The static method `instantiate()` acts as a constructor by accepting parameters named after its public properties. For discriminated DTOs, it resolves the discriminator value automatically.

The static method `from()` is suitable for unmarshalling payloads, such as decoded JSON, `stdClass`, `ArrayObject`or SPL data structures (that can be transformed into raw PHP composites).

Methods `lazyInstantiate()` and `lazyFrom()` creates lazy instances that initializes only when observed, which may reduce the number of previous CPU cycles when dealing with big nested DTOs and complex business logic partially navigating them.

Caution

Lazy DTO instantiations will defer exceptions that would otherwise have been thrown at creation time with their non-lazy corresponding methods only when they are observed for the first time; it is advised to unit test your work without lazy instances to validate your Data Transfer Object definitions.

```
