- What PHP and Laravel versions does std-out/simple-data-objects support?
- The package requires PHP 8.4 or newer, which is a hard floor rather than a preference. It works standalone or inside Laravel 12–13. If your fleet is still on PHP 8.2 or 8.3, adoption is gated behind a runtime upgrade or a separate service, so surface that platform cost before planning a rollout.
- How do I install and configure simple-data-objects in a Laravel app?
- Install it with composer require std-out/simple-data-objects, then register the opt-in service provider if you want framework integration. Configuration is minimal: point MetadataRegistry::setStoragePath() at the directory where compiled metadata should live. Because the package is not auto-discovered and does not touch Laravel's container or boot sequence, you can adopt it in a single module without affecting the rest of the application.
- Why is simple-data-objects faster than other Laravel DTO packages?
- Hydration and serialization compile to per-class closures, so there is zero reflection and no dispatch overhead at runtime. In benchmarks run inside a fully booted Laravel app with 20,000 iterations per scenario and medians of five runs, it measured roughly 50x faster for flat DTO hydration, 36x for nested DTOs, and 21x for a collection of 20. A companion benchmark repository lets you reproduce those numbers on your own hardware instead of trusting the table.
- How do I define a DTO and hydrate it from an array or Eloquent model?
- You declare a class extending StdOut\SimpleDataObjects\BaseData with typed, constructor-promoted properties and attributes describing casting, validation, and serialization. The from() method accepts arrays, Eloquent models, and Arrayable objects, so existing resource and transformer code has a mechanical migration path. Round-tripping is guaranteed, meaning from(toArray()) always works, mapped keys included. Keep the rule that only edge-layer classes extend BaseData: no entity, aggregate, or domain service should inherit from it.
- Does simple-data-objects work with Laravel's validator and my existing rule strings?
- Yes. Validation runs through Laravel's validator, so existing rule strings, custom rules, and message translations should carry over, and validation also works without a Laravel app when used standalone. Before committing, confirm that conditional rules such as Rule::when and sometimes, plus nested wildcards like items.*.price, behave as expected on your Laravel version. Failures collected via fromResult() accumulate as dot-path errors, which removes most hand-rolled 422 response assembly.
- Does simple-data-objects support nested DTOs and collections?
- Yes. Nested data objects and collections are first-class, and the published benchmark includes a collection-of-20 scenario alongside flat and nested hydration. Nested structures round-trip through toArray() and from(), so serialized payloads can be rehydrated without custom mapping code. This covers the common cases of request payloads with child objects, webhook bodies, and batched queue or CSV rows.
- How do I handle PATCH requests where a field is absent versus explicitly null?
- Use the Optional wrapper so a missing key and an explicit null are represented differently instead of collapsing into the same value. That gives correct PATCH semantics out of the box and replaces the array_key_exists checks many codebases currently use to distinguish an absent field from a deliberate null. It also keeps partial-update logic out of controllers and inside the DTO itself.
- Can simple-data-objects generate JSON Schema and TypeScript types for my API?
- Yes. jsonSchema() emits a schema from the same annotated class, and a companion TypeScript generator produces frontend .d.ts definitions. In practice one annotated class becomes the runtime contract, the OpenAPI fragment, and the frontend type, which removes drift between backend and frontend teams. Serialization attributes such as Hidden with an except list, Computed, and Flatten cover most of what API Resources do, with less ceremony.
- How does the compiled metadata cache behave in production deployments?
- Compiled metadata is written to disk at the path you configure, which introduces a deploy-time invariant that has to be managed deliberately. A metadata file that survives a DTO signature change can produce wrong output rather than an exception, making it a silent-failure class of bug. Treat cache warming with sdo-warm as release-engineering work, confirm the documented invalidation contract and how the cache is keyed, and decide how blue/green or rolling deploys interact with a cache directory that persists across releases.
- Is simple-data-objects production-ready and actively maintained?
- The signals are reasonable for a young package: MIT license, 100 percent coverage enforced in CI, a dedicated security workflow, a published changelog, documentation site, and a reproducible benchmark repository. It is still early-stage, with around 35 stars, no dependents, and a single maintainer, so adopting it means you effectively own your fork. Because the internals rely on compiled closures and generated cache files, confirm the maintainer's support model and backward-compatibility policy before you depend on it in a critical path.