laminas-diactoros provides the PSR-7 and PSR-17 objects behind Laminas HTTP
PSR HTTP Message implementations
At a glance
- What is it?
- laminas-diactoros is a PHP package with concrete implementations of the PSR-7 HTTP message interfaces and the PSR-17 factory interfaces, sitting underneath the Laminas HTTP stack so middleware and handlers can exchange messages without agreeing on a concrete class. It suits PHP teams standardising on FIG interfaces, and it is a low level building block rather than a framework.
- Who is it for?
- Adopt laminas-diactoros if your PHP code needs to produce or consume PSR-7 messages and you want the Laminas implementation rather than writing your own or pulling in a different vendor's version, because the interface contracts are what let middleware, PSR-15 handlers and PSR-17 factories be swapped independently.
- Can I use it commercially?
- Yes. BSD-3-Clause is a permissive licence: you can use, modify and sell software built on it, as long as you keep its copyright and licence notices.
- Is it still maintained?
- Yes. The repository last received commits 2 days ago.
- What is it written in?
- Mainly PHP, according to GitHub's language statistics.
Answers come from the project's GitHub data, last synced on October 22, 2026, and from our analysis. They are not legal advice.
Editorial analysis
The interfaces it implements and why they exist
laminas-diactoros is a PHP package containing implementations of the PSR-7 HTTP message interfaces and the PSR-17 HTTP message factory interfaces. That distinction between the two standards is the whole reason the package exists and the thing to understand before adopting it. PSR-7 defines the shape of an HTTP message: a request, a response, a URI, a stream, and the interfaces for headers and message bodies. It is an interface standard, so any implementation can be used. PSR-17, published by the PHP FIG, adds the factory interfaces that create those objects, which closes a gap PSR-7 left open, since PSR-7 describes what a message is but not who constructs it. The result is that a middleware written against PSR-15, a handler written against PSR-7 and a factory written against PSR-17 can be combined without any of them naming a concrete class. The package sits under the Laminas HTTP stack as the message implementation that the rest of the stack expects, and the topics tags for the repository are http-message, psr-7 and psr-17, which tells you the scope is deliberately narrow.
The lineage from phly/http
One line in the README answers a question a new maintainer would otherwise have to research: this package supercedes and replaces phly/http, the earlier HTTP message implementation from the same community. That history explains some of the design. The phly/http lineage predates the mainstreaming of PSR-7 in PHP tooling, so the codebase arrived with a mature, opinionated message model that later had to be expressed through the FIG interfaces, and the fact that the replacement happened at all suggests the older implementation had been carrying interface compatibility as a layer rather than as its foundation. For a team migrating, the practical question is whether anything in your code refers to phly/http classes directly, because those references do not survive the switch, whereas code that depends only on the PSR-7 and PSR-17 interfaces does. The README gives the project a name with a definition too, noting that Diactoros, pronounced /dɪʌktɒrɒs/, is an epithet for Hermes meaning literally the messenger, which is a reasonable description of a message implementation and a reminder that this is an infrastructure package rather than a product.
Where the source, tests and quality gates live
The repository layout is conventional for a Laminas project and tells you where to look for anything specific. The src/ directory holds the implementation, test/ holds the test suite, and docs/ holds the documentation sources, which the README confirms are the source files for the published documentation, built with mkdocs.yml. The tooling files show what the project expects of a contributor and of a consumer. phpcs.xml defines the coding standard, phpunit.xml.dist configures the test runner, and psalm.xml.dist with psalm-baseline.xml configures static analysis. The presence of a psalm baseline is a detail worth understanding rather than skipping: a baseline file lists known issues that are deliberately not reported, which means the analysed error count stays at zero and a new issue is visible when it appears, but it also means the baseline has to be regenerated when the analyser version changes. There is a .laminas-ci.json file for the Laminas continuous integration tooling, and renovate.json for dependency update automation, which is the mechanism behind keeping the package current.
The 3.x branch line and what a version bump costs
The default branch is 3.10.x, and the release history shows 3.9.0 published on 2026-10-08, before 3.8.0 on 2025-10-12 and 3.7.0 on 2025-10-11. Two things follow from those dates. The repository is not archived and the last push was on 2026-10-20, so the 3.10.x line is where current work lands, and it sits ahead of the latest tagged release rather than behind it. For a consumer that means a decision about which line to pin: the tagged 3.9.0 is a known release, while the 3.10.x branch is newer work that has not yet been cut as a release. The second point is about the upgrade surface. PSR-7 and PSR-17 are stable interfaces, so a minor bump inside 3.x is normally about implementation details rather than contract changes, but that is a property of the interface standards rather than a guarantee about any particular release, and the 3.7.0 and 3.8.0 tags landing on consecutive days in October 2025 suggests the pace of small releases can be quick. The licence is BSD-3-Clause, which is permissive, with the licence text in LICENSE.md and COPYRIGHT.md alongside it. Nothing in the BSD-3-Clause terms obliges a consumer to publish changes, though a downstream redistribution carries the usual requirement to retain the copyright and licence notices.
Getting it into a project
The README does not include a composer install command or a code sample, so the installation path is the one every PHP package follows and the one the project points at through its documentation, which is hosted at https://docs.laminas.dev/laminas-diactoros/. The package is published to Packagist under the laminas organisation, so the composer requirement is the laminas/laminas-diactoros package name, and the documentation site is where the version requirements and the usage examples live. The repository itself carries composer.json and composer.lock, which is the composer metadata for the package, including the PHP version constraint and the autoload mapping. The two FIG standard documents linked from the README are worth reading before you write code against this package, because the interface contracts are what your code should depend on and the Diactoros classes are the replaceable part. A reader coming from a framework that ships its own request and response objects will find the transition mostly mechanical, but a reader who has been calling concrete methods on framework request objects will need to check which behaviour lives in the interface and which lives in the implementation.
Support, security and the community side of the package
The README closes with the three links a maintainer or a user is expected to read, and each points to a shared Laminas repository rather than to a file in this one. Support documentation lives in the laminas/.github repository, the contributing guidelines sit next to it along with the Code of Conduct, and security issues go through a security policy in the same place. That structure matters for an infrastructure package, because a PSR-7 implementation sits in the path of every request your application handles, and a parsing or header handling defect in it has a wider blast radius than a defect in application code. It also means the security contact and the supported versions are defined centrally for the whole Laminas project family rather than per package. The README opens with a statement about the project's composition, noting that the Laminas contributors live in many countries, which is context for a package maintained by people spread across time zones, and it also contains the project's position on the war in Ukraine addressed to Russian citizens, a stance that has been part of the project since 2022.
Where laminas-diactoros is the wrong choice
The limits come from being a low level component. The first is that adopting it buys you interfaces, not convenience. If your application does not need to interchange message implementations, then depending on PSR-7 adds an abstraction layer and a class hierarchy without a corresponding benefit, and a plain client call is simpler. The second is the fragmentation risk that comes with the standard itself. PSR-7 and PSR-17 guarantee that the interfaces match, not that two implementations behave identically, so swapping vendors can change how a body stream is read, how a header is serialised, or how an empty body is represented, and those differences surface as subtle bugs in a framework rather than as an error. The third is version management in a large application, since laminas-diactoros interacts with every other Laminas component and a mismatch between the diactoros version, the laminas-http version and the PSR-15 bridge packages shows up as a type error at the boundary rather than as a clean failure. The fourth is that the package gives you no HTTP client and no server. Sending a request is the job of a PSR-18 client implementation, and there are several of those with different feature sets, so choosing diactoros does not narrow the number of decisions you have to make about the rest of your HTTP stack.
Editorial conclusion
Adopt laminas-diactoros if your PHP code needs to produce or consume PSR-7 messages and you want the Laminas implementation rather than writing your own or pulling in a different vendor's version, because the interface contracts are what let middleware, PSR-15 handlers and PSR-17 factories be swapped independently. Do not adopt it if all you need is to send an HTTP request, since a PSR-18 client or an ordinary curl call is the shorter path, and do not adopt it if you are on PHP 7, since the package targets the modern PHP range and an unsupported runtime is a hard stop. Verify two things before you upgrade: that your code depends on the PSR-7 and PSR-17 interfaces rather than on specific Diactoros classes, because the default branch is 3.10.x while the latest tagged release is 3.9.0, and that your static analysis and coding standard configuration still passes with the project's own psalm-baseline.xml. The practical first step is to add laminas/laminas-diactoros to composer.json and instantiate a request and a response through the PSR-17 factory interfaces before touching any middleware.
Frequently asked questions
What is laminas-diactoros?
It is a PHP package containing implementations of the PSR-7 HTTP message interfaces and the PSR-17 HTTP message factory interfaces, used by the Laminas HTTP stack. The project is BSD-3-Clause licensed and its documentation is at https://docs.laminas.dev/laminas-diactoros/.
What is the difference between PSR-7 and PSR-17 in laminas-diactoros?
PSR-7 defines the interfaces for HTTP messages such as requests, responses, URIs, streams and headers, while PSR-17 defines the factory interfaces that create those objects. Diactoros implements both, so a codebase can depend on the standards and swap the underlying implementation.
What replaced phly/http?
The README states that laminas-diactoros supercedes and replaces phly/http, the earlier HTTP message implementation. Code written against the PSR-7 and PSR-17 interfaces continues to work, while code referencing phly/http classes directly does not.
How do I install laminas-diactoros?
The README does not include an install command, and points to the documentation at https://docs.laminas.dev/laminas-diactoros/. The package is published under the laminas organisation, so it is added as the laminas/laminas-diactoros composer package, with composer.json and composer.lock in the repository holding the version requirements and autoload mapping.
Which version of laminas-diactoros should I use?
The default branch is 3.10.x and the latest tagged release is 3.9.0 from 2026-10-08, with the last push to the repository on 2026-10-20. So the 3.10.x line is newer than the released 3.9.0, and pinning the tagged release is the conservative choice for production deployments.
Official sources
Add this badge to your README
If you maintain this project, the badge below links readers to this analysis and shows its maintenance status from the daily GitHub snapshot. Paste the markdown into your README; add ?metric=license or ?metric=stars to the image URL for a different field.
[](https://hysenlabs.com/projects/laminas-laminas-diactoros)Was this useful?