TL;DR: attribute-driven DTOs are pleasant to write but usually pay a reflection-and-dispatch tax on every call. , and they're a perfect fit for DTOs. fromLazy() returns an uninitialized lazy ghost; the compiled argument resolver runs on first property access:
$orders = array_map(OrderData::fromLazy(...), $rows);
// casts, nested DTOs, pipes — none of it has run yet.
// Touch one property and that object (only) hydrates:
$orders[0]->title;
Both the eager hydrator and the lazy argument resolver are generated from the same code builder, so hydration semantics can't drift between the two paths.
When only ~10% of created objects are ever read — think "hydrate the page, render the visible rows" — this measures ~3× faster on cast-heavy DTOs and ~6× with nested collections. Honest footnote: for trivial flat DTOs the ghost bookkeeping costs about as much as it saves, so the docs say exactly that instead of pretending it's free speed.
And for the "million rows through a pipeline" case there's lazyCollection(), which hydrates one item at a time as the collection is consumed: streaming 50,000 rows peaks at ~0.26 MB instead of ~13 MB materialized.
The numbers
Benchmarked against the most popular full-featured data-object library in the PHP/Laravel ecosystem — identical DTO shapes, 20,000 iterations per scenario, PHP 8.4:
| Scenario | Simple Data Objects | Popular alternative | Advantage |
|---|---|---|---|
| Hydration — flat DTO | ~4,500,000 ops/s | ~130,000 ops/s | ~35× |
| Hydration — nested DTO | ~2,200,000 ops/s | ~74,000 ops/s | ~30× |
| Hydration — collection of 20 | ~270,000 ops/s | ~7,500 ops/s | ~36× |
| Serialization — flat DTO | ~7,400,000 ops/s | ~200,000 ops/s | ~37× |
| Serialization — nested DTO | ~4,000,000 ops/s | ~117,000 ops/s | ~34× |
| Peak memory — 50k rows | 0.26 MB (lazyCollection()) | ~13 MB | ~50× less |
Absolute numbers vary with hardware; the ratios stay stable across runs. To be fair to the alternative: it does more — it's a framework-integrated toolkit with TypeScript transformers, wire formats, and a large extension surface. If you use that surface, use it; it's excellent. This package targets the case where DTOs are on your hot path and you mostly need hydrate/validate/serialize — the 80% — as fast as PHP can go.
What you give up
Design honesty section. The speed comes from constraints:
PHP 8.4 only. Lazy ghosts, property hooks-era engine. No polyfills, no legacy branches.
Constructor-promoted, readonly properties are the model. No setters, no mutable state — which is also just correct DTO design.
No runtime magic. Everything the DTO does is declared in attributes and compiled ahead of time. If you need to rewire behavior per instance at runtime, this is the wrong tool.
What you don't give up: validation (Laravel rules, working standalone without a Laravel app), casts (dates, enums, JSON, encrypted fields via libsodium), input pipelines, key transforms, nested collections, immutable with()/diff()/equals(). The test suite covers 100% of lines, enforced in CI — the coverage gate fails below 100, and there are no @codeCoverageIgnore escapes.
Try it
composer require std-out/simple-data-objects
Blazing-fast attribute-driven DTOs for PHP 8.4+ — compiled hydrators, zero reflection in production, works standalone or with Laravel
Simple Data Objects
Why
| Simple Data Objects | |
|---|---|
| Hot path | Compiled per-class closures — zero reflection, zero dispatch overhead |
| Boilerplate | None — constructor props + attributes |
| Roundtrip | from(toArray()) always works, mapped keys included |
| Standalone | Validation works without a Laravel app |
| Pipelines | Middleware-style input preprocessing, class or property level |
Performance
Benchmarked against the most popular full-featured data-object library in the PHP/Laravel ecosystem — identical DTO shapes, 20,000 iterations per scenario, PHP 8.4:
| Scenario | Simple Data Objects | Popular alternative | Advantage |
|---|---|---|---|
| Hydration — flat DTO | ~4,500,000 ops/s | ~130,000 ops/s | ~35× faster |
| Hydration — nested DTO | ~2,200,000 ops/s | ~74,000 ops/s | ~30× faster |
| Hydration — collection of 20 | ~270,000 ops/s | ~7,500 ops/s | ~36× faster |
| Serialization — flat DTO | ~7,400,000 ops/s | ~200,000 ops/s | ~37× faster |
| Serialization — nested DTO | ~4,000,000 ops/s | ~117,000 ops/s | ~34× faster |
If you try it on a real workload, I'd genuinely like to hear the numbers — especially where it doesn't win. Benchmarks that survive contact with other people's production are the only ones that matter.
Community-Analysen & Experten-Meinungen 0
Verwandte Story-Cluster & Quellen (Vektor-KI)
Ähnliche Beiträge
Auch interessante Nachrichten Compiling PHP DTOs: from reflection to 4.5M hydrations per second
Thematisch verwandte Begriffe: Compiling, DTOs, from, reflection · 6 Treffer
Building Agentic RAG, Step by Step: From Static Retrieval to Reasoning Pipelines
EMOTET Configuration Extractor
Videos werden geladen ...
Beiträge werden geladen ...
Videos werden geladen ...
Beiträge werden geladen ...
Videos werden geladen ...
Beiträge werden geladen ...
Videos werden geladen ...
Beiträge werden geladen ...
Videos werden geladen ...
SOCIAL SHARE CARD GENERATOR