Weave Code
Weaver
Helps Laravel developers discover, compare, and choose open-source packages. See popularity, security, maintainers, and scores at a glance to make better decisions.
Feedback
Share your thoughts, report bugs, or suggest improvements.
Subject
Message

Laminas Diactoros Laravel Package

laminas/laminas-diactoros

Laminas Diactoros is a PHP PSR-7 implementation of HTTP messages, providing request, response, server request, stream, upload, and URI classes plus PSR-17 factories for interoperable web applications and middleware.

View on GitHub
Deep Wiki
Context7

Technical Evaluation

Verdict: This is a compliance-grade utility, not a framework component. For a Laravel codebase it is architecturally peripheral: Laravel's HTTP kernel is built on Symfony HttpFoundation (Illuminate\Http\Request/Response wrapping Symfony\Component\HttpFoundation\*), not PSR-7. Diactoros therefore never sits on the default request/response path. It earns its place only when a specific dependency is written against PSR-7/PSR-17.

Architecture fit — conditional.

  • Diactoros provides concrete implementations of PSR-7 v2 (Request, Response, ServerRequest, Stream, UploadedFile, Uri) and PSR-17 factories (ServerRequestFactory, ResponseFactory, StreamFactory, UploadedFileFactory, UriFactory).
  • It is a leaf library: it implements standards and does not prescribe an architecture. It cannot replace Laravel's router, middleware pipeline, or its Request/Response objects — attempting that is a rewrite, not an integration.
  • Realistic entry points in a Laravel app: (a) a third-party SDK or server library that type-hints Psr\Http\Message\*; (b) reusable PSR-15 middleware; (c) an outbound abstraction where you want PSR-18/PSR-7 instead of Guzzle's own types; (d) PSR-17 factories resolved from the container by interface.

Integration feasibility — high, but bridged.

  • Composer install only; no service provider, no config, no bootstrapping required. Zero coupling to the application container beyond optional interface bindings.
  • The real work is the bridge, not the package: converting Illuminate\Http\Request ⇄ PSR-7 ServerRequest via symfony/psr-http-message-bridge, and a PSR-7 Response back into a Symfony response. The seam is where the behavioral edge cases live (uploaded files, streamed bodies, header casing, multi-value headers).

Technical risk — low for the package, medium for the decision.

  • Package risk is low: BSD-3-Clause, PSR-7 v2 and PSR-17 compliant, active releases tracking PHP through 8.5, Roave Backward-Compatibility Check in CI, Psalm/type-coverage badges, a dedicated docs site and a maintained migration.md.
  • Decision risk is the real exposure: this is a choice of PSR-7 implementation, and it is not the one the Laravel/Symfony mainstream reaches for. nyholm/psr7 is the Symfony-recommended lightweight default; guzzlehttp/psr7 dominates outbound-client contexts. Diactoros carries Laminas/Mezzio heritage — solid, but a smaller community center of gravity for a Laravel shop.
  • "Dependents: 0" in the metadata is almost certainly a scan artifact (it is a dependency of Mezzio, Laminas MVC, and many others). Do not read it as a signal, but do confirm with composer why after install.
  • Minor: the README leads with a geopolitical statement. Technically irrelevant; worth a one-line note to comms/legal only if your org screens vendor content.

Key questions before adopting:

  1. What concrete dependency is forcing PSR-7? If none, stop here.
  2. Does that dependency accept any PSR-7 implementation, or does it pin a concrete one?
  3. Have we evaluated nyholm/psr7 and guzzlehttp/psr7 on equal footing (transitive dependency count, PSR-17 factory ergonomics)?
  4. Do we already have an HTTP client layer? If Guzzle or the Http facade covers the need, PSR-7 may be redundant.
  5. Is the app on PHP ≥ 8.2? (3.8.0 dropped 8.1; 3.3.0 dropped 8.0.)
  6. Who owns the Symfony↔PSR-7 bridge, and is that seam under test?

Integration Approach

Stack fit: Additive only. Install alongside Laravel; nothing in the framework changes. The one meaningful touchpoint is the container — bind the PSR-17 factory interfaces to Diactoros implementations so libraries resolve by interface rather than instantiating concrete types.

Recommended boundary: Treat Diactoros as an adapter layer at the edges — inbound conversion for libraries that demand a ServerRequest, outbound construction for libraries that emit a PSR-7 Response. Never let Laminas\Diactoros\* concrete types leak into controllers, domain code, or job payloads.

Migration path:

  • Greenfield: composer require laminas/laminas-diactoros, register factory bindings, wire the bridge only on the routes/SDK calls that need it.
  • Replacing another PSR-7 implementation: code against the PSR interfaces first, confirm there are no concrete-class references (new GuzzleHttp\Psr7\Response(), instanceof Nyholm\Psr7\...), then swap. Interface-level swaps are safe by construction; concrete-class usage is the only real lock-in, so grep for it before committing.
  • 3.0.0 was a BC break only for consumers extending Diactoros classes (PSR-7 v2 void return types on StreamInterface/UploadedFileInterface, removal of PhpInputStream, marshalUriFromSapi, and the Zend-namespaced helpers). Pure consumers can treat 3.x as a drop-in.

Compatibility: PSR-7 v2, PSR-17, PHP 8.2–8.5 on the 3.x line — a clean overlap with Laravel 11/12's PHP 8.2 floor. Watch for constraint conflicts if any legacy package still pins the 2.x line.

Sequencing (roughly two sprints for a scoped use case):

  1. Justify the dependency — name the library and the interface it demands. No justification, no install.
  2. Compare the three PSR-7 implementations on transitive dependency count and factory coverage; pick once and document why.
  3. Bind PSR-17 factories in a service provider; add a thin Symfony↔PSR-7 bridge service with its own test suite.
  4. Pilot on one non-critical integration (an outbound SDK or a single PSR-15 middleware).
  5. Add a static-analysis or lint rule banning concrete Diactoros types outside the adapter namespace.
  6. Roll out to remaining call sites.

Operational Impact

Maintenance: Low. Vendor code — no runtime services, no configuration, no migrations, no schema. It ships on a predictable minor cadence (several per year, mostly PHP-version support, QA tooling, and small fixes) with per-release notes and a maintained migration guide. The Roave BC check gives a credible "patch/minor won't break you" guarantee, which is exactly what you want from a dependency you plan to forget about. Realistic budget: one dependency-bump PR per PHP minor upgrade.

Support: Community-maintained through GitHub issues/PRs and the Laminas docs site; no commercial SLA unless Laminas support is purchased. This is the weakest dimension for a Laravel shop — your team, not the Laminas community, will be first responder for the problems you actually hit, because those problems will live in the Symfony↔PSR-7 seam rather than in Diactoros. A documented security policy exists, which matters for procurement review.

Scaling: Negligible throughput impact if the bridge is confined to specific endpoints. The cost to watch is per-request object churn: PSR-7 messages are immutable, so every header/body mutation clones, and full-body buffering duplicates memory. Applied as global middleware on every request, that is a small but real tax multiplied by RPS. Keep conversions at the edge, stream large bodies instead of materializing them, and never round-trip a request through PSR-7 and back "just in case."

Failure modes to design against:

  • Double-conversion drift — headers, cookies, and uploaded files losing fidelity across the bridge (casing, multi-value, + in cookie values). This is a real historical bug class here; 3.4.0 fixed cookie parsing from globals and +→space corruption.
  • Stream lifecycle — detached or closed streams; getMetadata() after detach raised errors before 3.4.0. Never hand one Diactoros stream to two consumers.
  • Immutability misuse — $response->withHeader(...) returns a new object; discarding the return value is a silent no-op. This is the most common developer error and it fails quietly.
  • Concrete-type leakage — a Laminas\Diactoros\Response in a controller signature quietly couples the app to this vendor.
  • Version-constraint stalls — an old package pinning ^2.x blocks the PHP 8.5 upgrade path.
  • Bridge-only coverage gaps — unit-test the adapter, not just the endpoints.

Ramp-up: Small but non-zero. The concepts a Laravel developer must internalize are PSR-7 immutability and stream semantics — both unlike Laravel's mutable, macro-heavy Request/Response. Budget half a day of onboarding plus code-review vigilance for the first few PRs; everything else (install, factories, bridging) is mechanical.

Bottom line for the roadmap: Do not adopt this as infrastructure. Adopt it as a narrowly scoped adapter when — and only when — a named dependency requires PSR-7/PSR-17. When that happens, standardize on one implementation across the codebase, code to interfaces, and confine concrete types to a single namespace. If no such dependency exists today, the correct TPM call is to defer, and to re-run this same evaluation against nyholm/psr7 when the need actually arrives.

Weaver

How can I help you explore Laravel packages today?

Conversation history is not saved when not logged in.
Prompt
Add packages to context
No packages found.
mehedimi/laravel-amp-mail
happones/laravel-vue-i18n-generator
jwerd/inertia-table
siberfx/flysystem-wasabi
hollyit/token-replace
ippanelcom/laravel-sdk
adachsoft/changelog-linter
adachsoft/collection
payerurl/telegrambot-crypto-payment-instant-payout
dskripchenko/laravel-hybrid-search
riorizkyrainey/lara-ced
mehedimi/static-vel
zharp/zharp
nonsapiens/bigquery-model-sync
lgu-bayambang-ict-office/lgu-laravel-development-standards
andydefer/laravel-support
se7enxweb/flysystem
lampwick/laravel
jeslage/statamic-emojis
micahdshackelford/rmap-laravel