TL;DR: attribute-driven DTOs are pleasant to write but usually pay a reflection-and-dispatch tax on every call. Simple Data Objects compiles a specialized closure per data class instead — plain properties become inline array reads, the generated code is persisted into an opcache-served cache, and PHP 8.4 lazy ghosts defer hydration until first property access. Here's the architecture, step by step, with numbers at each stage.

Every modern PHP codebase eventually grows a layer of data objects: typed, immutable classes that sit between raw input (a request, a DB row, an API payload) and your domain logic. Attribute-driven DTO libraries made this pleasant to write:

class CreateOrderData extends BaseData

{

public function __construct(