@@ -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-
634632Streaming 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
731714Serving Files
732715~~~~~~~~~~~~~
0 commit comments