symfony/psr7-pack
Symfony PSR-7 pack is a Composer metapackage that installs PSR-7 HTTP message interfaces, a lightweight PSR-7 implementation, and Symfony’s PSR HTTP message bridge for smooth interoperability.
symfony/psr7-pack is a Symfony Flex pack — a Composer metapackage whose only job is to declare a curated set of require entries so that composer require symfony/psr7-pack wires up a working PSR-7/PSR-17/PSR-18 stack (message bridge plus a concrete HTTP message implementation). It contains no application code, no service providers, and no runtime logic. Its architectural weight is therefore entirely in dependency resolution, not in execution.
Architecture fit. Packs are the sanctioned mechanism for "install the right combination of packages" in Symfony Flex. Adopting it is low-ceremony and idiomatic; nothing in our application code needs to reference the pack. Fit is good provided we treat it as an installer convenience rather than as a versioned contract we depend on semantically.
What v1.3.0 changes. The single commit replaces nyholm/psr7 with php-http/discovery in the pack's requirements. Practically this means:
nyholm/psr7 is installed. Any code path that reaches Nyholm\Psr7\* classes transitively (i.e. we never declared it ourselves) will now fail at autoload/runtime.php-http/discovery, which lets PSR-17/PSR-18 factory and client implementations be located at runtime rather than pinned. That is a genuine improvement for interoperability (HTTPlug/PSR-18 ecosystem, Symfony HttpClient bridges) and reduces hard coupling to one implementation.php-http/discovery also installs a Composer plugin that can rewrite/generate discovery metadata at install time — a new moving part in our build.Integration feasibility. High mechanically: it is a composer update in a Laravel app. Low-to-moderate in practice, because the change is a silent transitive dependency swap published under a minor version. Composer will not warn anyone; the failure surfaces later as a Class "Nyholm\Psr7\..." not found or a discovery exception.
Technical risk.
php-http/discovery ships a plugin; allow-plugins policy in CI or hardened environments may block it, producing a confusing install-time failure rather than a clear error.php-http/discovery strategy config or a direct require.Key questions for the maintainers / our team.
nyholm/psr7 intentional and permanent, or a transitional step toward discovery-first?Psr17Factory::registerFactory)?symfony/psr-http-message-bridge or symfony/http-client packs that we should coordinate with?Stack fit. Laravel apps that use PSR-7 at all usually do so through the Symfony PSR HTTP message bridge (e.g. for a PSR-7-based middleware, a signed-URL/HTTP client path, or a third-party SDK requiring PSR-18). We are on Laravel with Composer 2.x and Symfony Flex; the pack installs cleanly. The new dependency is compatible with our PHP version and does not conflict with Laravel's own HTTP layer, which is PSR-7-agnostic.
Migration path.
composer why nyholm/psr7 and composer show --tree filtered for psr/http-*, nyholm/psr7, symfony/psr-http-message-bridge. Classify each occurrence as direct (we declared it — safe) or transitive-only (at risk). Only transitive-only consumers are exposed.nyholm/psr7 as a direct requirement in composer.json. This makes the dependency ours, immunizes us against future pack churn, and is the single highest-value mitigation.composer require symfony/psr7-pack:^1.3 --no-update, then composer update symfony/psr7-pack php-http/discovery --with-dependencies. Diff the lockfile and confirm exactly which packages entered/left.config.allow-plugins permits php-http/discovery in both local and CI environments, or explicitly set it to false and configure discovery manually.Compatibility. No PHP or Laravel version constraints change. The break is dependency-graph-shaped, not API-shaped. Anything using only the bridge's interfaces is unaffected; anything touching Nyholm\Psr7\ concretely is affected.
Sequencing. (a) Pin Nyholm directly, deploy, confirm no behavior change. (b) Then take the pack upgrade in an isolated PR. (c) Then, separately, evaluate whether to adopt discovery-driven factory resolution — that is an architecture decision, not a dependency chore. Do not bundle (b) and (c).
Maintenance. Net positive if we pin. Direct dependencies on concrete PSR-7 implementations age better than implicit ones inherited from a metapackage. The pack itself remains near-zero maintenance. Countervailing cost: php-http/discovery adds a Composer plugin to our supply chain, which is one more thing to track in dependency review, and one more component whose behavior can shift on a Composer upgrade.
Support. Low support load at runtime — no daemon, no config, no service provider. Support risk concentrates in build-time confusion: a missing-class error six weeks after the fact, traced back to a metapackage bump, is a poor debugging experience for whoever is on call. Mitigate by writing the incident pattern down now ("missing Nyholm\Psr7 class → check symfony/psr7-pack history").
Scaling. Irrelevant in the throughput sense; this package does not sit on a request path. The scaling concern is organizational: number of services × silent dependency swaps. Codifying "no transitive reliance on metapackage-provided implementations" in our standards removes that scaling risk permanently.
Failure modes.
| Mode | Trigger | Signature | Blast radius |
|---|---|---|---|
| Missing class | Transitive-only Nyholm consumer after upgrade | Class "Nyholm\Psr7\..." not found |
Single feature, but possibly a critical one (auth-flow HTTP middleware) |
| Plugin blocked | allow-plugins not set in CI |
Composer install aborts | All deploys, loud and immediate (good) |
| Ambiguous factory | Discovery finds multiple/no implementations | Runtime discovery exception | Environment-specific, worst kind — works locally, fails in prod |
| Lockfile drift | Unpinned metapackage in a floating CI matrix | Non-reproducible builds across environments | Broad, silent |
Ramp-up. Trivial to learn (composer require, done) — which is precisely the trap. The team needs no product training but does need one piece of shared context: this package is a dependency list, not a library; its version numbers do not tell you whether your code still works. I would add a one-line note to the dependency-review checklist rather than run any dedicated session.
Recommendation. Accept v1.3.0, but only after making nyholm/psr7 (if used) and our PSR-17/PSR-18 expectations explicit in composer.json, and only after confirming plugin policy in CI. Treat the pack as a convenience installer we may eventually drop for a hand-curated require list — that is the end state that removes this entire class of surprise.
How can I help you explore Laravel packages today?