Skip to content

Commit 3be5f6a

Browse files
committed
Tweaks
1 parent 1091d89 commit 3be5f6a

File tree

1 file changed

+47
-64
lines changed

1 file changed

+47
-64
lines changed

components/http_foundation.rst

Lines changed: 47 additions & 64 deletions
Original file line numberDiff line numberDiff line change
@@ -629,8 +629,6 @@ represented by a PHP callable instead of a string::
629629
// disables FastCGI buffering in nginx only for this response
630630
$response->headers->set('X-Accel-Buffering', 'no');
631631

632-
.. _component-http-foundation-serving-files:
633-
634632
Streaming a JSON Response
635633
~~~~~~~~~~~~~~~~~~~~~~~~~
636634

@@ -639,94 +637,79 @@ Streaming a JSON Response
639637
The :class:`Symfony\\Component\\HttpFoundation\\StreamedJsonResponse` class was
640638
introduced in Symfony 6.3.
641639

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.
640+
The :class:`Symfony\\Component\\HttpFoundation\\StreamedJsonResponse` allows to
641+
stream large JSON responses using PHP generators to keep the used resources low.
644642

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 as 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.
650-
651-
The response will stream the JSON with generators in to most efficient way and keep resources as low as possible::
643+
The class constructor expects an array which represents the JSON structure and
644+
includes the list of contents to stream. In addition to PHP generators, which are
645+
recommended to minimize memory usage, it also supports any kind of PHP Traversable
646+
containing JSON serializable data::
652647

653648
use Symfony\Component\HttpFoundation\StreamedJsonResponse;
654649

655-
function loadArticles(): \Generator { // any method or function returning a Generator
650+
// any method or function returning a PHP Generator
651+
function loadArticles(): \Generator {
656652
yield ['title' => 'Article 1'];
657653
yield ['title' => 'Article 2'];
658654
yield ['title' => 'Article 3'];
659655
};
660656

661657
$response = new StreamedJsonResponse(
662-
// json structure with generators in which will be streamed as a list
658+
// JSON structure with generators in which will be streamed as a list
663659
[
664660
'_embedded' => [
665-
'articles' => loadArticles(), // any \Generator can be used which will be streamed as list of data
661+
'articles' => loadArticles(),
666662
],
667663
],
668664
);
669665

670-
.. tip::
671-
672-
If loading data via doctrine the ``toIterable`` method of ``Doctrine`` can be
673-
used to keep the resources low and fetch only row by row.
674-
See the `Doctrine Batch processing`_ documentation for more::
666+
When loading data via Doctrine, you can use the ``toIterable()`` method to
667+
fetch results row by row and minimize resources consumption.
668+
See the `Doctrine Batch processing`_ documentation for more::
675669

676-
public function __invoke(): Response
677-
{
678-
return new StreamedJsonResponse(
679-
[
680-
'_embedded' => [
681-
'articles' => $this->loadArticles(),
682-
],
670+
public function __invoke(): Response
671+
{
672+
return new StreamedJsonResponse(
673+
[
674+
'_embedded' => [
675+
'articles' => $this->loadArticles(),
683676
],
684-
);
685-
}
677+
],
678+
);
679+
}
686680

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');
681+
public function loadArticles(): \Generator
682+
{
683+
// get the $entityManager somehow (e.g. via constructor injection)
684+
$entityManager = ...
694685

695-
return $queryBuilder->getQuery()->toIterable();
696-
}
686+
$queryBuilder = $entityManager->createQueryBuilder();
687+
$queryBuilder->from(Article::class, 'article');
688+
$queryBuilder->select('article.id')
689+
->addSelect('article.title')
690+
->addSelect('article.description');
697691

698-
.. tip::
692+
return $queryBuilder->getQuery()->toIterable();
693+
}
699694

700-
If you have a lot of data to be returned you may 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::
695+
If you return a lot of data, consider calling the :phpfunction:`flush` function
696+
after some specific item count to send the contents to the browser::
703697

704-
public function __invoke(): Response
705-
{
706-
return new StreamedJsonResponse([
707-
'_embedded' => [
708-
'articles' => $this->loadArticles(),
709-
],
710-
]);
711-
}
698+
public function loadArticles(): \Generator
699+
{
700+
// ...
712701

713-
public function loadArticles(): \Generator
714-
{
715-
$queryBuilder = $entityManager->createQueryBuilder();
716-
$queryBuilder->from(Article::class, 'article');
717-
$queryBuilder->select('article.id')
718-
->addSelect('article.title')
719-
->addSelect('article.description');
720-
721-
$count = 0;
722-
foreach ($queryBuilder->getQuery()->toIterable() as $article) {
723-
yield $article;
724-
725-
if (++$count % 100 === 0) {
726-
flush();
727-
}
702+
$count = 0;
703+
foreach ($queryBuilder->getQuery()->toIterable() as $article) {
704+
yield $article;
705+
706+
if (0 === ++$count % 100) {
707+
flush();
728708
}
729709
}
710+
}
711+
712+
.. _component-http-foundation-serving-files:
730713

731714
Serving Files
732715
~~~~~~~~~~~~~

0 commit comments

Comments
 (0)