Skip to content

Commit ad83f47

Browse files
Update to new version of the class
1 parent 1f0b1c5 commit ad83f47

File tree

1 file changed

+80
-19
lines changed

1 file changed

+80
-19
lines changed

components/http_foundation.rst

Lines changed: 80 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -634,41 +634,102 @@ represented by a PHP callable instead of a string::
634634
Streaming a JSON Response
635635
~~~~~~~~~~~~~~~~~~~~~~~~~
636636

637-
.. versionadded:: 6.2
637+
.. versionadded:: 6.3
638+
639+
The :class:`Symfony\\Component\\HttpFoundation\\StreamedJsonResponse` class was
640+
introduced in Symfony 6.3.
641+
642+
The :class:`Symfony\\Component\\HttpFoundation\\StreamedJsonResponse` allows an API to
643+
return a lot of data as JSON and keep the used resources low by make usage of Generators.
638644

639-
The :class:`Symfony\\Component\\HttpFoundation\\StreamedJsonResponse` class allows
640-
an API to return a lot of data as JSON and keep the used resources low by make usage
641-
of Generators.
645+
It expects an array which represents the JSON structure and the list which should be
646+
streamed are represented in the array as ``\Generator``. It also supports any kind of
647+
Traversable containing JSON Serializable data for a good developer experience,
648+
but for keep the resources usage low as possible it is recommended to use ``\Generators``,
649+
as they the advantages that only the current returned data need to be keep in memory.
642650

643-
It expects a JSON structure with one or multiple replacers identifiers, as example
644-
the `'__articles__'`. As a second argument it requires one or multiple Generators
645-
which items can be converted to a JSON via ``json_encode`` method. The key of the
646-
Generators requires to be the used replacer identifiers::
651+
The response will stream the JSON with generators in to most efficient way and keep resources as low as possible::
647652

648653
use Symfony\Component\HttpFoundation\StreamedJsonResponse;
649654

655+
function loadArticles(): \Generator { // any method or function returning a Generator
656+
yield ['title' => 'Article 1'];
657+
yield ['title' => 'Article 2'];
658+
yield ['title' => 'Article 3'];
659+
};
660+
650661
$response = new StreamedJsonResponse(
651-
// json structure with replace identifiers
662+
// json structure with generators in which will be streamed as a list
652663
[
653664
'_embedded' => [
654-
'articles' => '__articles__',
665+
'articles' => loadArticles(), // any \Generator can be used which will be streamed as list of data
655666
],
656667
],
657-
// array of generators with replace identifier used as key
658-
[
659-
'__articles__' => (function (): \Generator { // any method or function returning a Generator
660-
yield ['title' => 'Article 1'];
661-
yield ['title' => 'Article 2'];
662-
yield ['title' => 'Article 3'];
663-
})(),
664-
]
665668
);
666669

667670
.. tip::
668671

669672
If loading data via doctrine the ``toIterable`` method of ``Doctrine`` can be
670673
used to keep also the resources low and fetch only one row one by one.
671-
See the `Doctrine Batch processing`_ documentation for more.
674+
See the `Doctrine Batch processing`_ documentation for more::
675+
676+
public function __invoke(): Response
677+
{
678+
return new StreamedJsonResponse(
679+
[
680+
'_embedded' => [
681+
'articles' => $this->loadArticles(),
682+
],
683+
],
684+
);
685+
}
686+
687+
public function loadArticles(): \Generator
688+
{
689+
$queryBuilder = $entityManager->createQueryBuilder();
690+
$queryBuilder->from(Article::class, 'article');
691+
$queryBuilder->select('article.id')
692+
->addSelect('article.title')
693+
->addSelect('article.description');
694+
695+
return $queryBuilder->getQuery()->toIterable();
696+
}
697+
698+
.. tip::
699+
700+
If you have a lot of data to be returned you maybe want to call the
701+
PHP `flush <https://www.php.net/manual/en/function.flush.php>`__ method between
702+
to flush the response after every specific count of items::
703+
704+
public function __invoke(): Response
705+
{
706+
return new StreamedJsonResponse(
707+
[
708+
'_embedded' => [
709+
'articles' => $this->loadArticles(),
710+
],
711+
],
712+
);
713+
}
714+
715+
public function loadArticles(): \Generator
716+
{
717+
$queryBuilder = $entityManager->createQueryBuilder();
718+
$queryBuilder->from(Article::class, 'article');
719+
$queryBuilder->select('article.id')
720+
->addSelect('article.title')
721+
->addSelect('article.description');
722+
723+
$count = 0;
724+
foreach ($queryBuilder->getQuery()->toIterable() as $article) {
725+
yield $article;
726+
727+
if (++$count % 100 === 0) {
728+
flush();
729+
}
730+
}
731+
}
732+
672733

673734
Serving Files
674735
~~~~~~~~~~~~~

0 commit comments

Comments
 (0)