PHPackages                             brnc/psr7-symfony1-adapter - PHPackages - PHPackages  [Skip to content](#main-content)[PHPackages](/)[Directory](/)[Categories](/categories)[Trending](/trending)[Leaderboard](/leaderboard)[Changelog](/changelog)[Analyze](/analyze)[Collections](/collections)[Log in](/login)[Sign up](/register)

1. [Directory](/)
2. /
3. [HTTP &amp; Networking](/categories/http)
4. /
5. brnc/psr7-symfony1-adapter

ActiveLibrary[HTTP &amp; Networking](/categories/http)

brnc/psr7-symfony1-adapter
==========================

Partial PSR-7 Adapters for Symfony 1.5

v1.6.1(1y ago)333.8k↓34.6%1[1 PRs](https://github.com/ebln/psr7-symfony1-adapter/pulls)MITPHPPHP ^7.4 || ^8.0CI passing

Since Dec 9Pushed 3mo agoCompare

[ Source](https://github.com/ebln/psr7-symfony1-adapter)[ Packagist](https://packagist.org/packages/brnc/psr7-symfony1-adapter)[ RSS](/packages/brnc-psr7-symfony1-adapter/feed)WikiDiscussions master Synced 1mo ago

READMEChangelog (10)Dependencies (13)Versions (20)Used By (0)

Partial PSR-7 Adapters for Symfony 1.5
======================================

[](#partial-psr-7-adapters-for-symfony-15)

To enable the use of future-proof PSR-15 middlewares via partial PSR-7 adapters.

Quickstart
----------

[](#quickstart)

```
// not fully PSR-7 compliant lazy adapters
$serverRequestAdapter = \brnc\Symfony1\Message\Adapter\Request::fromSfWebRequest($sfWebRequest);
$responseAdapter      = \brnc\Symfony1\Message\Adapter\Response::fromSfWebResponse($sfWebResponse);
```

ServerRequest
-------------

[](#serverrequest)

Please mind the following PSR-7 violation which is enabled by default:

### No immutability by default

[](#no-immutability-by-default)

as this is just an adapter for `\sfWebRequest` which cannot easily be replaced with another instance.

This adapter – by default – also returns the very same instance when calling `with*()` methods. For the same reason calls to methods which cannot act on and alter the underlying `\sfWebRequest`will throw an `\brnc\Symfony1\Message\Exception\LogicException`.

This default behaviour can be changed by creating the `Request` using the `Request::OPTION_IMMUTABLE_VIOLATION` option set to `false`. The `Request`-adapter will then always return new instances when `with*()`-methods are called and won't throw exceptions on calls which cannot transparently act on the `\sfWebRequest`- object.

```
use brnc\Symfony1\Message\Adapter\Request;

$serverRequestAdapter = Request::fromSfWebRequest(
    $sfWebRequest,
    [
        // If set to true a stream on php://input is used instead of creating one over sfWebRequest::getContent() → defaults to false
        Request::OPTION_BODY_USE_STREAM     => false,
        // sfWebRequest-compatibility mode – set to false if you need PSR-7's immutability
        Request::OPTION_IMMUTABLE_VIOLATION => true,
    ]
);
```

Response
--------

[](#response)

Please mind the default to mutability!

```
use brnc\Symfony1\Message\Adapter\Response;

$responseAdapter = Response::fromSfWebResponse(
    $sfWebResponse,
    [Response::OPTION_IMMUTABLE_VIOLATION => false]
);
$newInstance     = $responseAdapter->withBody(
    \GuzzleHttp\Psr7\Utils::streamFor(
        'Hello World!PSR-7 Adapters!'
    )
);
$newestInstance  = $newInstance->withBody(
    \GuzzleHttp\Psr7\Utils::streamFor(
        'dead end'
    )
);

// selects the content of $newInstance to be send instead of the most recent instance's one (i.e. $newestInstance)
$newInstance->preSend();
// N.b. The stream of $newestInstance is still held in memory until $responseAdapter and all copies got destroyed!
//      This might change in the future when this will be refactored to use WeakMap.

$sfWebResponse->send();
```

Pass it down to a PSR-15 sub-stack
----------------------------------

[](#pass-it-down-to-a-psr-15-sub-stack)

You may use the `ResponseFactory` implementing `\Psr\Http\Message\ResponseFactoryInterface` in order to "spawn" responses within your PSR-15 sub-stack.

```
$request         = \brnc\Symfony1\Message\Adapter\Request::fromSfWebRequest($sfWebRequest);
$responseFactory = new \brnc\Symfony1\Message\Factory\ResponseFactory($sfWebResponse);
// (dependency) inject the ResponseFactory to your dispatcher, middlewares, and handlers
$entryPoint      = new YourPSR15Dispatcher($responseFactory);
// Dispatch your sub-stack via PSR-15
$response        = $entryPoint->handler($response);
// As $response will be linked to $sfWebResponse you don't need to do anything
// if you are in the context of a Symfony1 action. Only call $response->getSfWebResponse() in dire need!
```

Manually transcribe a PSR-7 Response to Symfony1
------------------------------------------------

[](#manually-transcribe-a-psr-7-response-to-symfony1)

Assume you couldn't use other means, and you're confronted with an arbitrary PSR-7 response you can use the `ResponseTranscriptor` to copy the data from your PSR-7 response to your `\sfWebResponse`.

The `ResponseTranscriptor` by default uses `NoCookieTranscriptor`, which fails hard in the presence of `Set-Cookie'` headers. Incorporating (present-day) Cookies into the `\sfWebResponse` is not strait-forward. However, you are free to implement your own Cookie-Handler implementing `CookieTranscriptorInterface` and pass it as an optional constructor argument.

```
// Given arbitrary PSR-7 response…
$psr7response = $psr7responseFactory();
// …use the ResponseTranscriptor in order to–
$transcriptor = new \brnc\Symfony1\Message\Transcriptor\ResponseTranscriptor();
// copy the response's contents.
//   The returned object will be the same as in the argument!
$sfWebResponse = $transcriptor->transcribe($psr7response, $sfWebResponse);
```

### Implemented `CookieTranscriptorInterface`s

[](#implemented-cookietranscriptorinterfaces)

There are a few CookieTranscriptors already implemented; each come with their specific compromises.

#### `CookieHeaderTranscriptor`

[](#cookieheadertranscriptor)

Transcribes `Set-Cookie` headers from your PSR-7 response, into the cookie management of the Symfony1 response. This comes with all downsides of the legacy signature of `setrawcookie()`. Foremost it's not supporting `SameSite`-attribute, nor everything else being `extension-av` as of RFC 265.

#### `AbstractCookieDispatchTranscriptor`

[](#abstractcookiedispatchtranscriptor)

The (abstract) CookieDispatchTranscriptor uses reflection and swaps the response's EventDispatcher against a new one. It is very tied against the original implementation of `sfWebResponse::sendHttpHeaders` especially its logging mechanism via events. The `CookieDispatcher` puts itself between `sfWebResponse` and the original `sfEventDispatcher`, and fires the cookies from the PSR-7 response right before Symfony1 would have sent theirs. You need to implement `AbstractCookieDispatchTranscriptor`'s `transcribeCookies()` method, depending on your source for the cookies being set. E.g. if your using a 3rd party library. Your code eventually needs to return `CookieContainerInterface` full of `CookieInterface`s. There is already a `HeaderCookie`, that uses `header()` and expects an already crafted and complete `Set-Cookie`-headerline. There are also `SetCookie` and `SetRawCookie` which will use the respective methods with the new signature – i.e. three arguments, with the options-array as a third one.

Pass it down to http-foundation i.e. present-day Symfony
--------------------------------------------------------

[](#pass-it-down-to-http-foundation-ie-present-day-symfony)

Combine this PSR7-Symfony1 Adapter and `symfony/psr-http-message-bridge` to connect your Symfony1 stack via PSR-7 to `symfony/http-foundation` objects and leverage using embedded (present-day) Symfony components.

```
// Use this chain to create a http-foundation request from a Symfony1's \sfWebRequest
$psrRequest            = \brnc\Symfony1\Message\Adapter\Request::fromSfWebRequest($sfWebRequest);
$httpFoundationFactory = \Symfony\Bridge\PsrHttpMessage\Factory\HttpFoundationFactory();
$symfonyRequest        = $httpFoundationFactory->createRequest($psrRequest);

// Handle the request with some present day Symfony component
$symfonyResponse = $httpKernel->handle($symfonyRequest);

// Possibly ResponseFactory is best created in the Symfony1 context
$responseFactory = new \brnc\Symfony1\Message\Factory\ResponseFactory($sfWebResponse);

// Obtain other PSR17 factories,
//   while only ResponseFactory & StreamFactory will be used (as of today)
$streamFactory   = \brnc\Symfony1\Message\Factory\GuzzleStreamFactory();
$decoyFactory    = \brnc\Symfony1\Message\Factory\DecoyHttpFactory();
// Construct the PsrHttpFactory from symfony/psr-http-message-bridge and translate…
$psrHttpFactory  = Symfony\Bridge\PsrHttpMessage\Factory\PsrHttpFactory(
    $decoyFactory, $streamFactory, $decoyFactory, $responseFactory
);
$psrResponse     = $psrHttpFactory->createResponse($symfonyResponse);
// As $psrResponse will be linked to $sfWebResponse as it was created through the
// ResponseFactory you don't need to do anything if you exit via an Symfony1 action.
// Only call $psrResponse->getSfWebResponse() in dire need!
```

###  Health Score

48

—

FairBetter than 94% of packages

Maintenance59

Moderate activity, may be stable

Popularity31

Limited adoption so far

Community7

Small or concentrated contributor base

Maturity75

Established project with proven stability

 Bus Factor1

Top contributor holds 100% of commits — single point of failure

How is this calculated?**Maintenance (25%)** — Last commit recency, latest release date, and issue-to-star ratio. Uses a 2-year decay window.

**Popularity (30%)** — Total and monthly downloads, GitHub stars, and forks. Logarithmic scaling prevents top-heavy scores.

**Community (15%)** — Contributors, dependents, forks, watchers, and maintainers. Measures real ecosystem engagement.

**Maturity (30%)** — Project age, version count, PHP version support, and release stability.

###  Release Activity

Cadence

Every ~118 days

Recently: every ~248 days

Total

18

Last Release

704d ago

Major Versions

v0.2.0 → v1.0.12020-07-05

PHP version history (3 changes)v0.0.2PHP ^5.6 || ^7.0

v1.0.1PHP ^7.2

v1.2.0PHP ^7.4 || ^8.0

### Community

Maintainers

![](https://avatars.githubusercontent.com/u/8059635?v=4)[brnc](/maintainers/brnc)[@brnc](https://github.com/brnc)

---

Top Contributors

[![ebln](https://avatars.githubusercontent.com/u/34722048?v=4)](https://github.com/ebln "ebln (348 commits)")

---

Tags

psr-15psr-7symfony1httppsr-7http-messagemessagesymfony1

###  Code Quality

TestsPHPUnit

Static AnalysisPHPStan, Psalm

Type Coverage Yes

### Embed Badge

![Health badge](/badges/brnc-psr7-symfony1-adapter/health.svg)

```
[![Health](https://phpackages.com/badges/brnc-psr7-symfony1-adapter/health.svg)](https://phpackages.com/packages/brnc-psr7-symfony1-adapter)
```

###  Alternatives

[guzzlehttp/psr7

PSR-7 message implementation that also provides common utility methods

8.0k1.0B3.2k](/packages/guzzlehttp-psr7)[phpro/http-tools

HTTP tools for developing more consistent HTTP implementations.

28137.8k](/packages/phpro-http-tools)[mezzio/mezzio-authentication-oauth2

OAuth2 (server) authentication middleware for Mezzio and PSR-7 applications.

28483.0k2](/packages/mezzio-mezzio-authentication-oauth2)[httpsoft/http-message

Strict and fast implementation of PSR-7 and PSR-17

86874.0k94](/packages/httpsoft-http-message)[mezzio/mezzio-authentication

Authentication middleware for Mezzio and PSR-7 applications

121.6M26](/packages/mezzio-mezzio-authentication)[art4/requests-psr18-adapter

Use WordPress/Requests as a PSR-18 HTTP client

153.3k](/packages/art4-requests-psr18-adapter)

PHPackages © 2026

[Directory](/)[Categories](/categories)[Trending](/trending)[Changelog](/changelog)[Analyze](/analyze)
