yiisoft/data-response
yiisoft/data-response provides a PSR-7 response wrapper for returning structured data from your application. It supports multiple output formats, content negotiation, and streaming, making it easy to send JSON, XML, HTML, or raw data consistently.
Architecture fit: yiisoft/data-response is a PSR-7/PSR-15 middleware package from the Yii ecosystem, not a Laravel package. It converts arbitrary PHP data structures into HTTP responses with content negotiation (HTML/JSON/XML/plain text). For a Laravel codebase, this is an architectural mismatch: Laravel's ResponseFactory, JsonResponse, and Responsable interface already occupy this space, and Laravel's middleware pipeline is not PSR-15. Fit is acceptable only if the target service is framework-agnostic (plain PSR-7/PSR-15 stack, RoadRunner/Swoole worker, or a Yii3 service sharing a monorepo with Laravel components via a bridge such as nyholm/psr7 + a PSR-15 adapter). Treat "Laravel/PHP package" in the brief as "PHP package being evaluated for a PHP estate that is predominantly Laravel" — do not assume drop-in Laravel support.
Integration feasibility: 2.2.0 is a net-new public API layered on top of the existing one rather than a rewrite. The new surface is coherent and small in concept count: one DataStream value object, one FormatterInterface with four implementations, a family of *ResponseFactory classes, a family of PSR-15 middlewares, plus ContentNegOTiatorResponseFactory/ContentNegotiatorDataResponseMiddleware for negotiation. Integration is feasible at the HTTP boundary of a service: wrap a domain payload in DataStream, hand it to a factory, and let the middleware format it. No database, queue, or container coupling is introduced. The main feasibility friction is wiring: PSR-15 middleware must be bridged into Laravel's kernel or run in a separate PSR-15 app, and the package still expects a PSR-17 factory implementation to be supplied by the host.
Technical risk: Moderate-to-high, driven almost entirely by the deprecation wave. 2.2.0 deprecates 15 named symbols — DataResponse, DataResponseFactory, DataResponseFactoryInterface, DataResponseFormatterInterface, ResponseContentTrait, the four *DataResponseFormatter classes, ContentNegotiator, and the four FormatDataResponse* middleware — which is effectively the entire 1.x/2.0/2.1 usage surface. Anyone who integrated the prior API is now on a deprecation clock with no stated removal version. Secondary risks: (a) two parallel API generations will coexist for at least one minor cycle, so examples found in the wild will be split roughly 50/50 and half of them will emit deprecation notices; (b) the package is pre-1.0-stability in spirit despite the 2.x version — Yii packages routinely break at minor boundaries; (c) low community volume relative to Laravel-ecosystem packages means fewer Stack Overflow answers and slower issue turnaround; (d) DataStream semantics (streaming vs. buffering, memory behavior on large payloads) are new and unproven under load.
Key questions: Which of our services, if any, are genuinely PSR-7/PSR-15 rather than Laravel-native? Is there an existing 2.1-era integration in the estate that now needs a deprecation-remediation ticket? What is the upstream removal timeline for the deprecated symbols, and will it land in 2.x or 3.0? Does DataStream buffer the full payload before formatting (relevant for large exports)? Who owns the PSR-17/PSR-7 implementation choice, and is it already a dependency elsewhere? Is there a supported Laravel bridge, or would we be writing and owning one?
Stack fit: Poor fit for a conventional Laravel application — do not introduce this as a replacement for response()->json() or Laravel's Responsable. Good fit for a shared, framework-neutral HTTP layer: an internal API gateway, a BFF service, or a Yii3 service that must interoperate with Laravel consumers. Where a Laravel app must consume it, the correct shape is "Laravel calls a PSR-15 service over HTTP," not "Laravel loads this package."
Migration path: Because the current assessment is empty, there is no incumbent integration to migrate — this is a greenfield adoption decision, not an upgrade. If a 2.1-era integration is discovered during discovery, migrate in one pass to the new API rather than straddling both: DataResponse → DataStream + *ResponseFactory; *DataResponseFormatter → *Formatter; FormatDataResponse* middleware → *DataResponseMiddleware; ContentNegotiator → ContentNegotiatorResponseFactory / ContentNegotiatorDataResponseMiddleware. Pin ^2.2 in composer.json and add a composer why-not / deprecation-notice check to CI so the parallel old API cannot silently creep back in.
Compatibility: Requires PHP 8.x (per Yii3 baseline) and PSR-7/PSR-15/PSR-17 implementations. Does not depend on Laravel, Symfony HttpFoundation, or Yii's DI container, which is the point — but it also means nothing is auto-wired. Verify the chosen PSR-7 implementation (nyholm/psr7, guzzlehttp/psr7) does not collide with versions already pinned by Laravel's HTTP client. Composer footprint was trimmed in #108, which helps.
Sequencing: (1) Confirm framework-neutrality requirement and pick the host service — do not adopt speculatively. (2) Spike a single endpoint: DataStream → JsonResponseFactory → PSR-15 middleware, behind the existing edge. (3) Establish the PSR-7/17 implementation and middleware bridge as a shared internal package so each service does not re-solve it. (4) Only after the spike, decide whether content negotiation (the ContentNegotiator* classes) is needed — it is the most opinionated and least exercised part of 2.2.0 and can be deferred. (5) Hold any estate-wide standardisation until the deprecation removal version is known upstream.
Maintenance: Low ongoing code maintenance — the package is small, dependency-light, and its new architecture is more modular than what it replaces. The real maintenance cost is the deprecation backlog: if we adopt 2.2.0 we inherit a clean API, but every future minor may repeat this pattern. Budget for a version-review on each release rather than assuming semver stability.
Support: Upstream is a single-maintainer-led Yii package (@vjik authored essentially all of 2.2.0). Bus factor and response latency are materially worse than Laravel-first alternatives. Internal capability must therefore be the primary support line; assume no vendor SLA.
Scaling: Stateless PSR-15 middleware scales horizontally without ceremony. The unknown is DataStream: if it materialises payloads in memory before formatting, large collection endpoints will show memory growth that Laravel's streamed responses would not. Benchmark one representative large payload before committing to high-volume endpoints. Content negotiation adds a small per-request cost and a cache-variance concern if responses are CDN-cached without Vary: Accept discipline.
Failure modes: (a) Deprecated-symbol usage lingering in code and failing silently at a future removal — mitigate with CI deprecation gates. (b) Middleware mis-ordering in a bridged PSR-15/Laravel pipeline, producing double-formatted or unformatted responses — the failure is usually a 200 with wrong Content-Type, which is easy to miss in tests; assert content type explicitly. (c) Negotiation falling back to an unexpected format on absent/ambiguous Accept headers, leaking HTML where JSON was expected. (d) PSR-7 implementation drift between the service and its consumers on header casing and stream rewind behaviour. (e) Memory exhaustion on large DataStream payloads.
Ramp-up: Conceptually small — a competent PHP engineer learns the new API in under a day. The cost is environmental, not conceptual: PSR-7/15/17 literacy, a middleware bridge that does not exist in Laravel, and the discipline to ignore the large body of 2.1-era documentation and blog posts still describing the now-deprecated classes. Estimate one engineer-week for the spike including the bridge, plus a half-day of team knowledge transfer. Do not fund broader training until the first service is live.
How can I help you explore Laravel packages today?