Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
76 commits
Select commit Hold shift + click to select a range
4b6d6fd
start
vjik Jan 15, 2026
cf6f77f
implement
vjik Jan 15, 2026
b4ec9a6
Apply PHP CS Fixer and Rector changes (CI)
vjik Jan 15, 2026
1b7d137
rename
vjik Jan 15, 2026
ad3fcf6
Merge remote-tracking branch 'origin/refactor' into refactor
vjik Jan 15, 2026
20e0eff
refactor
vjik Jan 17, 2026
f8c7f67
improve
vjik Jan 20, 2026
67e783f
revert formatters
vjik Jan 25, 2026
97f21aa
Rename formatter files and update namespaces to improve organization
vjik Jan 25, 2026
cdf773f
Add DataStream
vjik Jan 25, 2026
7efb553
Apply PHP CS Fixer and Rector changes (CI)
vjik Jan 25, 2026
a831d66
improve
vjik Jan 25, 2026
7677ccc
Merge remote-tracking branch 'origin/refactor' into refactor
vjik Jan 25, 2026
46e5555
improve
vjik Jan 26, 2026
4f09ea9
improve
vjik Jan 26, 2026
873de7c
Apply PHP CS Fixer and Rector changes (CI)
vjik Jan 26, 2026
bff8592
improve
vjik Jan 26, 2026
305e15e
Merge remote-tracking branch 'origin/refactor' into refactor
vjik Jan 26, 2026
0f2a245
Apply PHP CS Fixer and Rector changes (CI)
vjik Jan 26, 2026
102224c
improve
vjik Jan 26, 2026
14c10c3
Merge remote-tracking branch 'origin/refactor' into refactor
vjik Jan 26, 2026
043a332
improve
vjik Jan 26, 2026
fca3c4f
improve
vjik Jan 26, 2026
75605b5
improve
vjik Jan 27, 2026
7f7e146
Introduce `FormattedResponseFactoryInterface`
vjik Jan 27, 2026
cb1280b
Introduce `ContentNegotiator`
vjik Jan 27, 2026
a4d0e67
Introduce `LazyFormattingStream`
vjik Jan 29, 2026
e9ee3d9
Apply PHP CS Fixer and Rector changes (CI)
vjik Jan 29, 2026
eda5c26
improve
vjik Jan 29, 2026
343f9f4
Fix properties
vjik Jan 30, 2026
cc5a83a
Improve `DataResponseFactory`
vjik Jan 30, 2026
1603a94
Remove `FormattedResponseFactoryInterface`
vjik Jan 30, 2026
d913432
Improve `DataResponseFactory`
vjik Jan 31, 2026
935eead
Merge branch 'master' into refactor
vjik Feb 1, 2026
762efd8
Fix `JsonFormatted`
vjik Feb 1, 2026
d420ebb
Merge remote-tracking branch 'origin/refactor' into refactor
vjik Feb 1, 2026
b1d032f
move files
vjik Feb 2, 2026
8180994
start tests
vjik Feb 2, 2026
2fe60c9
Apply PHP CS Fixer and Rector changes (CI)
vjik Feb 2, 2026
6b72757
tests
vjik Feb 3, 2026
3880f9c
tests
vjik Feb 3, 2026
ea76d7d
tests
vjik Feb 3, 2026
2ef792a
tests
vjik Feb 3, 2026
cad79a6
Merge remote-tracking branch 'origin/refactor' into refactor
vjik Feb 3, 2026
5d66a9c
Apply PHP CS Fixer and Rector changes (CI)
vjik Feb 3, 2026
0369bf1
deprecations
vjik Feb 3, 2026
42a31b3
Merge remote-tracking branch 'origin/refactor' into refactor
vjik Feb 3, 2026
dfab4fd
Apply PHP CS Fixer and Rector changes (CI)
vjik Feb 3, 2026
8f5b167
Add `DataEncodingException`
vjik Feb 4, 2026
a6fd488
fix psalm
vjik Feb 4, 2026
7664bd0
Merge remote-tracking branch 'origin/refactor' into refactor
vjik Feb 4, 2026
c56c1e6
fix
vjik Feb 4, 2026
1bf531f
Apply PHP CS Fixer and Rector changes (CI)
vjik Feb 4, 2026
bb61efd
phpdoc
vjik Feb 4, 2026
a6d2c03
config
vjik Feb 4, 2026
c98c582
Apply PHP CS Fixer and Rector changes (CI)
vjik Feb 4, 2026
3e4ae11
docs
vjik Feb 4, 2026
103332a
Merge remote-tracking branch 'origin/refactor' into refactor
vjik Feb 4, 2026
93846b6
changelog
vjik Feb 4, 2026
894834e
Merge branch 'master' into refactor
vjik Feb 5, 2026
7081609
Allow use `RequestHandlerInterface` as fallback
vjik Feb 5, 2026
4c6bafe
NotAcceptableRequestHandler
vjik Feb 5, 2026
96e5565
rename
vjik Feb 5, 2026
1ae5cd8
fix
vjik Feb 5, 2026
d20ecec
fix
vjik Feb 5, 2026
06f6198
improve test
vjik Feb 5, 2026
0f6a5a3
fix
vjik Feb 5, 2026
8abcb19
improve test
vjik Feb 5, 2026
b288908
Apply PHP CS Fixer and Rector changes (CI)
vjik Feb 5, 2026
b085961
fix
vjik Feb 5, 2026
9e144d2
fix
vjik Feb 5, 2026
7e539a8
fix
vjik Feb 5, 2026
b5401f1
use stable yiisoft/test-support
vjik Feb 5, 2026
b0cb987
improve
vjik Feb 6, 2026
bb703f5
Merge remote-tracking branch 'origin/refactor' into refactor
vjik Feb 6, 2026
a5704a3
Apply PHP CS Fixer and Rector changes (CI)
vjik Feb 6, 2026
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
13 changes: 13 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,19 @@

## 2.1.3 under development

- New #107: Add `DataStream` (@vjik)
- New #107: Add `FormatterInterface` and implementations: `HtmlFormatter`, `JsonFormatter`, `PlainTextFormatter`,
`XmlFormatter` (@vjik)
- New #107: Add `DataResponseFactoryInterface` and implementations: `DataResponseFactory`, `FormattedResponseFactory`,
`HtmlResponseFactory`, `JsonResponseFactory`, `PlainTextResponseFactory`, `XmlResponseFactory` (@vjik)
- New #107: Add middlewares: `XmlDataResponseMiddleware`, `HtmlDataResponseMiddleware`, `JsonDataResponseMiddleware`,
`PlainTextDataResponseMiddleware` and `DataResponseMiddleware` (@vjik)
- New #107: Add `ContentNegotiatorResponseFactory` and `ContentNegotiatorDataResponseMiddleware` (@vjik)
- Chg #107: Deprecate `DataResponse`, `DataResponseFactory`, `DataResponseFactoryInterface`,
`DataResponseFormatterInterface`, `ResponseContentTrait`, `HtmlDataResponseFormatter`,
`JsonDataResponseFormatter`, `PlainTextDataResponseFormatter`, `XmlDataResponseFormatter`, `ContentNegotiator`,
`FormatDataResponse`, `FormatDataResponseAsHtml`, `FormatDataResponseAsJson`, `FormatDataResponseAsPlainText`,
`FormatDataResponseAsXml` (@vjik)
- Enh #106: Explicitly import classes, functions, and constants in "use" section (@mspirkov)
- Enh #108: Remove unnecessary files from Composer package (@mspirkov)

Expand Down
150 changes: 91 additions & 59 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -32,99 +32,131 @@ composer require yiisoft/data-response

## General usage

The package provides `DataResponseFactory` class that, given a [PSR-17](https://www.php-fig.org/psr/psr-17/)
response factory, is able to create data response.
### Response Factories

Data response contains raw data to be processed later.
The package provides response factories that create [PSR-7](https://www.php-fig.org/psr/psr-7/) responses
with `DataStream` body. The data is formatted lazily when the response body is read.

```php
use Yiisoft\DataResponse\DataResponseFactory;
use Yiisoft\DataResponse\ResponseFactory\JsonResponseFactory;
use Yiisoft\DataResponse\Formatter\JsonFormatter;

/**
* @var Psr\Http\Message\ResponseFactoryInterface $responseFactory
*/

$factory = new DataResponseFactory($responseFactory);
$dataResponse = $factory->createResponse('test');
$dataResponse
->getBody()
->rewind();
$factory = new JsonResponseFactory($responseFactory, new JsonFormatter());
$response = $factory->createResponse(['key' => 'value']);

echo $dataResponse
->getBody()
->getContents(); // "test"
$response->getBody()->rewind();
echo $response->getBody()->getContents(); // {"key":"value"}
echo $response->getHeaderLine('Content-Type'); // application/json; charset=UTF-8
```

### Formatters
The following response factories are available:

Formatter purpose is to format a data response. In the following example we format data as JSON.
- `JsonResponseFactory` — creates responses with JSON-formatted body;
- `XmlResponseFactory` — creates responses with XML-formatted body;
- `HtmlResponseFactory` — creates responses with HTML-formatted body;
- `PlainTextResponseFactory` — creates responses with plain text body;
- `DataResponseFactory` — creates responses without a predefined formatter, use middleware to format.

```php
use Yiisoft\DataResponse\DataResponseFactory;
use Yiisoft\DataResponse\Formatter\JsonDataResponseFormatter;
### Middleware

/**
* @var Psr\Http\Message\ResponseFactoryInterface $responseFactory
*/
The package provides [PSR-15](https://www.php-fig.org/psr/psr-15/) middleware that formats `DataStream` responses
without a predefined formatter.

```php
use Yiisoft\DataResponse\Middleware\JsonDataResponseMiddleware;
use Yiisoft\DataResponse\Formatter\JsonFormatter;

$factory = new DataResponseFactory($responseFactory);
$dataResponse = $factory->createResponse('test');
$dataResponse = $dataResponse->withResponseFormatter(new JsonDataResponseFormatter());
$dataResponse
->getBody()
->rewind();

echo $dataResponse->getHeader('Content-Type'); // ["application/json; charset=UTF-8"]
echo $dataResponse
->getBody()
->getContents(); // "test"
$middleware = new JsonDataResponseMiddleware(new JsonFormatter());
```

The following formatters are available:
The following middleware are available:

- `HtmlDataResponseFormatter`
- `JsonDataResponseFormatter`
- `XmlDataResponseFormatter`
- `PlainTextDataResponseFormatter`
- `HtmlDataResponseMiddleware`
- `JsonDataResponseMiddleware`
- `XmlDataResponseMiddleware`
- `PlainTextDataResponseMiddleware`

### Middleware
### Content Negotiation

The package provides a [PSR-15](https://www.php-fig.org/psr/psr-15/) middleware that is able to format a data response.
The package provides content negotiation via middleware and response factory.

```php
use Yiisoft\DataResponse\Middleware\FormatDataResponse;
use Yiisoft\DataResponse\Formatter\JsonDataResponseFormatter;
#### Middleware

$middleware = (new FormatDataResponse(new JsonDataResponseFormatter()));
//$middleware->process($request, $handler);
`ContentNegotiatorDataResponseMiddleware` selects a formatter based on the request's `Accept` header:

```php
use Yiisoft\DataResponse\Formatter\HtmlFormatter;
use Yiisoft\DataResponse\Formatter\XmlFormatter;
use Yiisoft\DataResponse\Formatter\JsonFormatter;
use Yiisoft\DataResponse\Middleware\ContentNegotiatorDataResponseMiddleware;

$middleware = new ContentNegotiatorDataResponseMiddleware(
formatters: [
'text/html' => new HtmlFormatter(),
'application/xml' => new XmlFormatter(),
'application/json' => new JsonFormatter(),
],
fallback: new JsonFormatter(),
);
```

Also, the package provides [PSR-15](https://www.php-fig.org/psr/psr-15/) middleware for content negotiation:
The `fallback` parameter also accepts a `RequestHandlerInterface`, for example `NotAcceptableRequestHandler`
to return a 406 response when no formatter matches.

#### Response Factory

`ContentNegotiatorResponseFactory` selects a response factory based on the request's `Accept` header:

```php
use Yiisoft\DataResponse\Formatter\HtmlDataResponseFormatter;
use Yiisoft\DataResponse\Formatter\XmlDataResponseFormatter;
use Yiisoft\DataResponse\Formatter\JsonDataResponseFormatter;
use Yiisoft\DataResponse\Middleware\ContentNegotiator;

$middleware = new ContentNegotiator([
'text/html' => new HtmlDataResponseFormatter(),
'application/xml' => new XmlDataResponseFormatter(),
'application/json' => new JsonDataResponseFormatter(),
]);
use Yiisoft\DataResponse\ResponseFactory\ContentNegotiatorResponseFactory;
use Yiisoft\DataResponse\ResponseFactory\JsonResponseFactory;
use Yiisoft\DataResponse\ResponseFactory\XmlResponseFactory;

/**
* @var JsonResponseFactory $jsonResponseFactory
* @var XmlResponseFactory $xmlResponseFactory
*/

$factory = new ContentNegotiatorResponseFactory(
factories: [
'application/json' => $jsonResponseFactory,
'application/xml' => $xmlResponseFactory,
],
fallback: $jsonResponseFactory,
);

$response = $factory->createResponse($request, ['key' => 'value']);
```

You can override middlewares with method `withContentFormatters()`:
The `fallback` parameter also accepts a `RequestHandlerInterface`, for example `NotAcceptableRequestHandler`
to return a 406 response when no factory matches.

### DataStream

`DataStream` is a [PSR-7](https://www.php-fig.org/psr/psr-7/) stream that lazily formats data.
It wraps raw data and a formatter, and performs formatting only when the stream is read.

```php
$middleware->withContentFormatters([
'application/xml' => new XmlDataResponseFormatter(),
'application/json' => new JsonDataResponseFormatter(),
]);
use Yiisoft\DataResponse\DataStream\DataStream;
use Yiisoft\DataResponse\Formatter\JsonFormatter;
use Yiisoft\DataResponse\Formatter\XmlFormatter;

$stream = new DataStream(['key' => 'value'], new JsonFormatter());

echo (string) $stream; // {"key":"value"}

// You can change the data or formatter dynamically
$stream->changeData(['new' => 'data']);
$stream->changeFormatter(new XmlFormatter());
```

## Documentation

- [Deprecated classes](docs/deprecated.md)
- [Internals](docs/internals.md)

If you need help or have a question, the [Yii Forum](https://forum.yiiframework.com/c/yii-3-0/63) is a good place for that.
Expand Down
5 changes: 3 additions & 2 deletions composer.json
Original file line number Diff line number Diff line change
Expand Up @@ -46,7 +46,8 @@
"rector/rector": "^2.1.4",
"roave/infection-static-analysis-plugin": "^1.35",
"vimeo/psalm": "^5.26.1 || ^6.8.0",
"yiisoft/di": "^1.4"
"yiisoft/di": "^1.4",
"yiisoft/test-support": "^3.2"
},
"autoload": {
"psr-4": {
Expand Down Expand Up @@ -82,6 +83,6 @@
},
"scripts": {
"require-checker": "composer-require-checker",
"test": "phpunit --testdox --no-interaction"
"test": "phpunit --testdox"
}
}
40 changes: 37 additions & 3 deletions config/di-web.php
Original file line number Diff line number Diff line change
Expand Up @@ -2,21 +2,55 @@

declare(strict_types=1);

use Yiisoft\DataResponse\DataResponseFactory;
use Yiisoft\DataResponse\DataResponseFactoryInterface;
use Yiisoft\DataResponse\DataResponseFactory as DeprecatedDataResponseFactory;
use Yiisoft\DataResponse\DataResponseFactoryInterface as DeprecatedDataResponseFactoryInterface;
use Yiisoft\DataResponse\DataResponseFormatterInterface;
use Yiisoft\DataResponse\Formatter\HtmlDataResponseFormatter;
use Yiisoft\DataResponse\Formatter\HtmlFormatter;
use Yiisoft\DataResponse\Formatter\JsonFormatter;
use Yiisoft\DataResponse\Formatter\XmlFormatter;
use Yiisoft\DataResponse\Middleware\ContentNegotiator;
use Yiisoft\DataResponse\Middleware\ContentNegotiatorDataResponseMiddleware;
use Yiisoft\DataResponse\NotAcceptableRequestHandler;
use Yiisoft\DataResponse\ResponseFactory\ContentNegotiatorResponseFactory;
use Yiisoft\DataResponse\ResponseFactory\DataResponseFactory;
use Yiisoft\DataResponse\ResponseFactory\DataResponseFactoryInterface;
use Yiisoft\DataResponse\ResponseFactory\HtmlResponseFactory;
use Yiisoft\DataResponse\ResponseFactory\JsonResponseFactory;
use Yiisoft\DataResponse\ResponseFactory\XmlResponseFactory;
use Yiisoft\Definitions\DynamicReferencesArray;
use Yiisoft\Definitions\Reference;
use Yiisoft\Definitions\ReferencesArray;

/* @var $params array */

return [
DataResponseFormatterInterface::class => HtmlDataResponseFormatter::class,
DataResponseFactoryInterface::class => DataResponseFactory::class,
DeprecatedDataResponseFactoryInterface::class => DeprecatedDataResponseFactory::class,
ContentNegotiator::class => [
'__construct()' => [
'contentFormatters' => DynamicReferencesArray::from($params['yiisoft/data-response']['contentFormatters']),
],
],
DataResponseFactoryInterface::class => DataResponseFactory::class,
ContentNegotiatorDataResponseMiddleware::class => [
'__construct()' => [
'formatters' => ReferencesArray::from([
'text/html' => HtmlFormatter::class,
'application/xml' => XmlFormatter::class,
'application/json' => JsonFormatter::class,
]),
'fallback' => Reference::to(NotAcceptableRequestHandler::class),
],
],
ContentNegotiatorResponseFactory::class => [
'__construct()' => [
'factories' => DynamicReferencesArray::from([
'text/html' => HtmlResponseFactory::class,
'application/xml' => XmlResponseFactory::class,
'application/json' => JsonResponseFactory::class,
]),
'fallback' => Reference::to(NotAcceptableRequestHandler::class),
],
],
];
97 changes: 97 additions & 0 deletions docs/deprecated.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,97 @@
# Deprecated

> [!WARNING]
> The classes described in this document are deprecated and will be removed in a future version.

## General usage

The package provides `DataResponseFactory` class that, given a [PSR-17](https://www.php-fig.org/psr/psr-17/)
response factory, is able to create data response.

Data response contains raw data to be processed later.

```php
use Yiisoft\DataResponse\DataResponseFactory;

/**
* @var Psr\Http\Message\ResponseFactoryInterface $responseFactory
*/

$factory = new DataResponseFactory($responseFactory);
$dataResponse = $factory->createResponse('test');
$dataResponse
->getBody()
->rewind();

echo $dataResponse
->getBody()
->getContents(); // "test"
```

## Formatters

Formatter purpose is to format a data response. In the following example we format data as JSON.

```php
use Yiisoft\DataResponse\DataResponseFactory;
use Yiisoft\DataResponse\Formatter\JsonDataResponseFormatter;

/**
* @var Psr\Http\Message\ResponseFactoryInterface $responseFactory
*/

$factory = new DataResponseFactory($responseFactory);
$dataResponse = $factory->createResponse('test');
$dataResponse = $dataResponse->withResponseFormatter(new JsonDataResponseFormatter());
$dataResponse
->getBody()
->rewind();

echo $dataResponse->getHeader('Content-Type'); // ["application/json; charset=UTF-8"]
echo $dataResponse
->getBody()
->getContents(); // "test"
```

The following formatters are available:

- `HtmlDataResponseFormatter`
- `JsonDataResponseFormatter`
- `XmlDataResponseFormatter`
- `PlainTextDataResponseFormatter`

## Middleware

The package provides a [PSR-15](https://www.php-fig.org/psr/psr-15/) middleware that is able to format a data response.

```php
use Yiisoft\DataResponse\Middleware\FormatDataResponse;
use Yiisoft\DataResponse\Formatter\JsonDataResponseFormatter;

$middleware = (new FormatDataResponse(new JsonDataResponseFormatter()));
//$middleware->process($request, $handler);
```

Also, the package provides [PSR-15](https://www.php-fig.org/psr/psr-15/) middleware for content negotiation:

```php
use Yiisoft\DataResponse\Formatter\HtmlDataResponseFormatter;
use Yiisoft\DataResponse\Formatter\XmlDataResponseFormatter;
use Yiisoft\DataResponse\Formatter\JsonDataResponseFormatter;
use Yiisoft\DataResponse\Middleware\ContentNegotiator;

$middleware = new ContentNegotiator([
'text/html' => new HtmlDataResponseFormatter(),
'application/xml' => new XmlDataResponseFormatter(),
'application/json' => new JsonDataResponseFormatter(),
]);
```

You can override middlewares with method `withContentFormatters()`:

```php
$middleware->withContentFormatters([
'application/xml' => new XmlDataResponseFormatter(),
'application/json' => new JsonDataResponseFormatter(),
]);
```
Loading