Response Types
Response Types
~12 Min. Lesezeit Zuletzt aktualisiert am August 8, 2026
Besides the simple Response from previous chapters, Symfony has several specialized response classes – each for a concrete, recurring use case.
JsonResponse: returning structured data
use Symfony\Component\HttpFoundation\JsonResponse;
#[Route('/projects/{id}/summary', name: 'project_summary', requirements: ['id' => '\d+'])]
public function summary(int $id): JsonResponse
{
return $this->json([
'id' => $id,
'name' => 'Website Relaunch',
'taskCount' => 12,
]);
}$this->json(...) (from AbstractController) automatically sets Content-Type: application/json and handles JSON serialization – preferable to manual json_encode() plus new Response(...).
RedirectResponse: redirecting to another route
#[Route('/projects/new', name: 'project_new', methods: ['POST'])]
public function new(Request $request): Response
{
// ... create the project (block 4) ...
return $this->redirectToRoute('project_index');
}Recall chapter 7: redirectToRoute() takes the ROUTE NAME, NEVER a hardcoded URL – if project_index's path changes later, this redirect keeps working correctly regardless.
// With route parameters:
return $this->redirectToRoute('project_show', ['id' => $project->getId()]);
// External URL (rarely needed):
return $this->redirect('https://example.com');BinaryFileResponse: file downloads
use Symfony\Component\HttpFoundation\BinaryFileResponse;
use Symfony\Component\HttpFoundation\ResponseHeaderBag;
#[Route('/projects/{id}/export', name: 'project_export', requirements: ['id' => '\d+'])]
public function export(int $id): BinaryFileResponse
{
$filePath = $this->getParameter('kernel.project_dir') . '/var/exports/project-' . $id . '.csv';
$response = new BinaryFileResponse($filePath);
$response->setContentDisposition(
ResponseHeaderBag::DISPOSITION_ATTACHMENT,
sprintf('project-%d.csv', $id)
);
return $response;
}DISPOSITION_ATTACHMENT triggers a "Save As" dialog instead of an inline display in the browser. $this->getParameter('kernel.project_dir') returns the ABSOLUTE path to the project root – never hardcode a relative path, which would resolve differently depending on the execution context.
StreamedResponse: large amounts of data without a memory blowup
use Symfony\Component\HttpFoundation\StreamedResponse;
#[Route('/projects/export-all', name: 'project_export_all')]
public function exportAll(): StreamedResponse
{
$response = new StreamedResponse(function () {
$handle = fopen('php://output', 'w');
fputcsv($handle, ['ID', 'Name']);
foreach ($this->iterateAllProjects() as $project) {
fputcsv($handle, [$project['id'], $project['name']]);
}
fclose($handle);
});
$response->headers->set('Content-Type', 'text/csv');
return $response;
}Achtung: StreamedResponse is only worth it for LARGE amounts of data that could exceed available PHP memory – for small CSV exports (like our task manager's case), a regular Response with a fully assembled body is entirely sufficient. Premature optimization without real need only makes code more complex.
Overview: which response type for what
| Class | Use case |
|---|---|
| Response | HTML, plain text, or Twig-rendered markup. |
| JsonResponse | Structured data for JavaScript/API clients. |
| RedirectResponse | Redirecting to another page after a successful POST (Post/Redirect/Get pattern). |
| BinaryFileResponse | Offering an EXISTING file for download. |
| StreamedResponse | LARGE, dynamically generated output without building it fully in memory. |