请求与响应 #

一、Request对象 #

1.1 获取Request对象 #

php
<?php

namespace App\Controller;

use Symfony\Bundle\FrameworkBundle\Controller\AbstractController;
use Symfony\Component\HttpFoundation\Request;
use Symfony\Component\HttpFoundation\Response;
use Symfony\Component\Routing\Annotation\Route;

class RequestController extends AbstractController
{
    #[Route('/request', name: 'app_request')]
    public function index(Request $request): Response
    {
        return new Response('Request received');
    }
}

1.2 Request属性 #

php
<?php

class RequestInfoController extends AbstractController
{
    #[Route('/request-info', name: 'app_request_info')]
    public function info(Request $request): Response
    {
        $info = [
            'method' => $request->getMethod(),
            'uri' => $request->getUri(),
            'path' => $request->getPathInfo(),
            'scheme' => $request->getScheme(),
            'host' => $request->getHost(),
            'port' => $request->getPort(),
            'ip' => $request->getClientIp(),
            'userAgent' => $request->headers->get('User-Agent'),
            'contentType' => $request->headers->get('Content-Type'),
            'isSecure' => $request->isSecure(),
            'isAjax' => $request->isXmlHttpRequest(),
        ];

        return $this->json($info);
    }
}

二、获取请求参数 #

2.1 查询参数(GET) #

php
<?php

class QueryController extends AbstractController
{
    #[Route('/search', name: 'app_search')]
    public function search(Request $request): Response
    {
        $keyword = $request->query->get('keyword', '');
        $page = $request->query->getInt('page', 1);
        $limit = $request->query->getInt('limit', 10);
        $sort = $request->query->get('sort', 'created_at');

        return $this->json([
            'keyword' => $keyword,
            'page' => $page,
            'limit' => $limit,
            'sort' => $sort,
        ]);
    }

    #[Route('/filter', name: 'app_filter')]
    public function filter(Request $request): Response
    {
        $allParams = $request->query->all();
        $hasKeyword = $request->query->has('keyword');
        $categories = $request->query->all('category');

        return $this->json([
            'all' => $allParams,
            'has_keyword' => $hasKeyword,
            'categories' => $categories,
        ]);
    }
}

2.2 表单数据(POST) #

php
<?php

class FormController extends AbstractController
{
    #[Route('/form/submit', name: 'app_form_submit', methods: ['POST'])]
    public function submit(Request $request): Response
    {
        $name = $request->request->get('name');
        $email = $request->request->get('email');
        $message = $request->request->get('message');

        return $this->json([
            'name' => $name,
            'email' => $email,
            'message' => $message,
        ]);
    }

    #[Route('/form/all', name: 'app_form_all', methods: ['POST'])]
    public function allData(Request $request): Response
    {
        $allData = $request->request->all();
        
        return $this->json($allData);
    }
}

2.3 JSON数据 #

php
<?php

class JsonController extends AbstractController
{
    #[Route('/api/data', name: 'api_data', methods: ['POST'])]
    public function data(Request $request): Response
    {
        $content = $request->getContent();
        $data = json_decode($content, true);

        return $this->json([
            'received' => $data,
        ]);
    }

    #[Route('/api/user', name: 'api_user_create', methods: ['POST'])]
    public function createUser(Request $request): Response
    {
        $data = json_decode($request->getContent(), true);

        $name = $data['name'] ?? '';
        $email = $data['email'] ?? '';

        return $this->json([
            'status' => 'created',
            'name' => $name,
            'email' => $email,
        ], Response::HTTP_CREATED);
    }
}

2.4 文件上传 #

php
<?php

class UploadController extends AbstractController
{
    #[Route('/upload', name: 'app_upload', methods: ['POST'])]
    public function upload(Request $request): Response
    {
        $file = $request->files->get('file');

        if (!$file) {
            return $this->json(['error' => 'No file uploaded'], 400);
        }

        $originalName = $file->getClientOriginalName();
        $mimeType = $file->getMimeType();
        $size = $file->getSize();
        $extension = $file->getClientOriginalExtension();

        $destination = $this->getParameter('kernel.project_dir') . '/public/uploads';
        $newFilename = uniqid() . '.' . $extension;
        $file->move($destination, $newFilename);

        return $this->json([
            'original_name' => $originalName,
            'mime_type' => $mimeType,
            'size' => $size,
            'new_filename' => $newFilename,
        ]);
    }

    #[Route('/upload/multiple', name: 'app_upload_multiple', methods: ['POST'])]
    public function uploadMultiple(Request $request): Response
    {
        $files = $request->files->all('files');
        $uploadedFiles = [];

        foreach ($files as $file) {
            $originalName = $file->getClientOriginalName();
            $newFilename = uniqid() . '.' . $file->getClientOriginalExtension();
            
            $file->move(
                $this->getParameter('kernel.project_dir') . '/public/uploads',
                $newFilename
            );

            $uploadedFiles[] = [
                'original' => $originalName,
                'saved' => $newFilename,
            ];
        }

        return $this->json(['files' => $uploadedFiles]);
    }
}

三、请求头 #

3.1 获取请求头 #

php
<?php

class HeaderController extends AbstractController
{
    #[Route('/headers', name: 'app_headers')]
    public function headers(Request $request): Response
    {
        $contentType = $request->headers->get('Content-Type');
        $authorization = $request->headers->get('Authorization');
        $userAgent = $request->headers->get('User-Agent');
        $accept = $request->headers->get('Accept');
        $allHeaders = $request->headers->all();

        return $this->json([
            'content_type' => $contentType,
            'authorization' => $authorization,
            'user_agent' => $userAgent,
            'accept' => $accept,
        ]);
    }

    #[Route('/api/auth', name: 'api_auth')]
    public function auth(Request $request): Response
    {
        $authHeader = $request->headers->get('Authorization');

        if (!$authHeader || !str_starts_with($authHeader, 'Bearer ')) {
            return $this->json(['error' => 'Unauthorized'], 401);
        }

        $token = substr($authHeader, 7);

        return $this->json([
            'token' => $token,
        ]);
    }
}

3.2 常用请求头 #

php
<?php

class CommonHeaderController extends AbstractController
{
    #[Route('/common-headers', name: 'app_common_headers')]
    public function commonHeaders(Request $request): Response
    {
        return $this->json([
            'host' => $request->headers->get('Host'),
            'origin' => $request->headers->get('Origin'),
            'referer' => $request->headers->get('Referer'),
            'accept_language' => $request->headers->get('Accept-Language'),
            'accept_encoding' => $request->headers->get('Accept-Encoding'),
            'cache_control' => $request->headers->get('Cache-Control'),
            'x_forwarded_for' => $request->headers->get('X-Forwarded-For'),
            'x_requested_with' => $request->headers->get('X-Requested-With'),
        ]);
    }
}

四、Cookie和Session #

4.1 Cookie操作 #

php
<?php

use Symfony\Component\HttpFoundation\Cookie;

class CookieController extends AbstractController
{
    #[Route('/cookie/get', name: 'app_cookie_get')]
    public function getCookie(Request $request): Response
    {
        $value = $request->cookies->get('my_cookie', 'default');
        $allCookies = $request->cookies->all();

        return $this->json([
            'my_cookie' => $value,
            'all' => $allCookies,
        ]);
    }

    #[Route('/cookie/set', name: 'app_cookie_set')]
    public function setCookie(): Response
    {
        $response = new Response('Cookie set');
        
        $cookie = Cookie::create('my_cookie')
            ->withValue('cookie_value')
            ->withExpires(strtotime('+1 year'))
            ->withPath('/')
            ->withDomain('.example.com')
            ->withSecure(true)
            ->withHttpOnly(true)
            ->withSameSite(Cookie::SAMESITE_LAX);

        $response->headers->setCookie($cookie);

        return $response;
    }

    #[Route('/cookie/delete', name: 'app_cookie_delete')]
    public function deleteCookie(): Response
    {
        $response = new Response('Cookie deleted');
        $response->headers->clearCookie('my_cookie');

        return $response;
    }
}

4.2 Session操作 #

php
<?php

use Symfony\Component\HttpFoundation\Session\SessionInterface;

class SessionController extends AbstractController
{
    #[Route('/session/set', name: 'app_session_set')]
    public function setSession(SessionInterface $session): Response
    {
        $session->set('user_id', 123);
        $session->set('username', 'john_doe');
        $session->set('cart', ['product_id' => 1, 'quantity' => 2]);

        return new Response('Session set');
    }

    #[Route('/session/get', name: 'app_session_get')]
    public function getSession(SessionInterface $session): Response
    {
        $userId = $session->get('user_id');
        $username = $session->get('username', 'guest');
        $cart = $session->get('cart', []);
        $all = $session->all();

        return $this->json([
            'user_id' => $userId,
            'username' => $username,
            'cart' => $cart,
            'all' => $all,
        ]);
    }

    #[Route('/session/remove', name: 'app_session_remove')]
    public function removeSession(SessionInterface $session): Response
    {
        $session->remove('user_id');
        $session->remove('cart');

        return new Response('Session removed');
    }

    #[Route('/session/clear', name: 'app_session_clear')]
    public function clearSession(SessionInterface $session): Response
    {
        $session->clear();

        return new Response('Session cleared');
    }

    #[Route('/session/flash', name: 'app_session_flash')]
    public function flashMessage(SessionInterface $session): Response
    {
        $session->getFlashBag()->add('success', '操作成功!');
        $session->getFlashBag()->add('info', '这是一条提示信息');

        return $this->redirectToRoute('app_session_show_flash');
    }

    #[Route('/session/show-flash', name: 'app_session_show_flash')]
    public function showFlash(SessionInterface $session): Response
    {
        $successMessages = $session->getFlashBag()->get('success');
        $infoMessages = $session->getFlashBag()->get('info');

        return $this->json([
            'success' => $successMessages,
            'info' => $infoMessages,
        ]);
    }
}

五、Response对象 #

5.1 创建响应 #

php
<?php

use Symfony\Component\HttpFoundation\Response;
use Symfony\Component\HttpFoundation\JsonResponse;
use Symfony\Component\HttpFoundation\RedirectResponse;

class ResponseController extends AbstractController
{
    #[Route('/response/text', name: 'app_response_text')]
    public function text(): Response
    {
        return new Response('Plain text response');
    }

    #[Route('/response/html', name: 'app_response_html')]
    public function html(): Response
    {
        $html = '<html><body><h1>HTML Response</h1></body></html>';
        
        return new Response($html);
    }

    #[Route('/response/json', name: 'app_response_json')]
    public function json(): JsonResponse
    {
        return new JsonResponse([
            'status' => 'success',
            'data' => ['id' => 1, 'name' => 'John'],
        ]);
    }

    #[Route('/response/redirect', name: 'app_response_redirect')]
    public function redirect(): RedirectResponse
    {
        return new RedirectResponse($this->generateUrl('app_home'));
    }
}

5.2 响应状态码 #

php
<?php

class StatusCodeController extends AbstractController
{
    #[Route('/status/200', name: 'app_status_200')]
    public function ok(): Response
    {
        return new Response('OK', Response::HTTP_OK);
    }

    #[Route('/status/201', name: 'app_status_201')]
    public function created(): Response
    {
        return new Response('Created', Response::HTTP_CREATED);
    }

    #[Route('/status/204', name: 'app_status_204')]
    public function noContent(): Response
    {
        return new Response('', Response::HTTP_NO_CONTENT);
    }

    #[Route('/status/400', name: 'app_status_400')]
    public function badRequest(): Response
    {
        return new Response('Bad Request', Response::HTTP_BAD_REQUEST);
    }

    #[Route('/status/401', name: 'app_status_401')]
    public function unauthorized(): Response
    {
        return new Response('Unauthorized', Response::HTTP_UNAUTHORIZED);
    }

    #[Route('/status/403', name: 'app_status_403')]
    public function forbidden(): Response
    {
        return new Response('Forbidden', Response::HTTP_FORBIDDEN);
    }

    #[Route('/status/404', name: 'app_status_404')]
    public function notFound(): Response
    {
        return new Response('Not Found', Response::HTTP_NOT_FOUND);
    }

    #[Route('/status/500', name: 'app_status_500')]
    public function serverError(): Response
    {
        return new Response('Internal Server Error', Response::HTTP_INTERNAL_SERVER_ERROR);
    }
}

5.3 响应头设置 #

php
<?php

class ResponseHeaderController extends AbstractController
{
    #[Route('/header/custom', name: 'app_header_custom')]
    public function customHeader(): Response
    {
        $response = new Response('Custom headers');
        
        $response->headers->set('X-Custom-Header', 'value');
        $response->headers->set('X-API-Version', '1.0');

        return $response;
    }

    #[Route('/header/cache', name: 'app_header_cache')]
    public function cacheControl(): Response
    {
        $response = new Response('Cached content');
        
        $response->setPublic();
        $response->setMaxAge(3600);
        $response->setSharedMaxAge(3600);
        $response->setETag('unique-identifier');

        return $response;
    }

    #[Route('/header/no-cache', name: 'app_header_no_cache')]
    public function noCache(): Response
    {
        $response = new Response('No cache content');
        
        $response->headers->addCacheControlDirective('no-cache');
        $response->headers->addCacheControlDirective('no-store');
        $response->headers->addCacheControlDirective('must-revalidate');

        return $response;
    }

    #[Route('/header/content-type', name: 'app_header_content_type')]
    public function contentType(): Response
    {
        $response = new Response('{"status": "ok"}');
        
        $response->headers->set('Content-Type', 'application/json');

        return $response;
    }
}

5.4 JSON响应 #

php
<?php

class JsonResponsetController extends AbstractController
{
    #[Route('/json/simple', name: 'app_json_simple')]
    public function simple(): JsonResponse
    {
        return $this->json(['message' => 'Hello World']);
    }

    #[Route('/json/status', name: 'app_json_status')]
    public function withStatus(): JsonResponse
    {
        return $this->json(
            ['status' => 'created', 'id' => 123],
            Response::HTTP_CREATED
        );
    }

    #[Route('/json/headers', name: 'app_json_headers')]
    public function withHeaders(): JsonResponse
    {
        return $this->json(
            ['data' => 'value'],
            Response::HTTP_OK,
            [
                'X-Custom-Header' => 'value',
                'X-API-Version' => '1.0',
            ]
        );
    }

    #[Route('/json/context', name: 'app_json_context')]
    public function withContext(): JsonResponse
    {
        $data = [
            'date' => new \DateTime(),
            'user' => new class {
                public $name = 'John';
                public $email = 'john@example.com';
            },
        ];

        return $this->json($data, Response::HTTP_OK, [], [
            'json_encode_options' => JSON_PRETTY_PRINT | JSON_UNESCAPED_UNICODE,
        ]);
    }
}

六、StreamedResponse #

6.1 流式响应 #

php
<?php

use Symfony\Component\HttpFoundation\StreamedResponse;

class StreamController extends AbstractController
{
    #[Route('/stream/csv', name: 'app_stream_csv')]
    public function csv(): StreamedResponse
    {
        $response = new StreamedResponse(function () {
            $handle = fopen('php://output', 'w');
            
            fputcsv($handle, ['ID', 'Name', 'Email']);
            fputcsv($handle, [1, 'John', 'john@example.com']);
            fputcsv($handle, [2, 'Jane', 'jane@example.com']);
            fputcsv($handle, [3, 'Bob', 'bob@example.com']);
            
            fclose($handle);
        });

        $response->headers->set('Content-Type', 'text/csv');
        $response->headers->set('Content-Disposition', 'attachment; filename="users.csv"');

        return $response;
    }

    #[Route('/stream/large-file', name: 'app_stream_large_file')]
    public function largeFile(): StreamedResponse
    {
        $response = new StreamedResponse(function () {
            $handle = fopen($this->getParameter('kernel.project_dir') . '/data/large_file.txt', 'r');
            
            while (!feof($handle)) {
                echo fread($handle, 8192);
                flush();
            }
            
            fclose($handle);
        });

        $response->headers->set('Content-Type', 'application/octet-stream');

        return $response;
    }
}

七、BinaryFileResponse #

7.1 文件下载 #

php
<?php

use Symfony\Component\HttpFoundation\BinaryFileResponse;
use Symfony\Component\HttpFoundation\ResponseHeaderBag;

class FileController extends AbstractController
{
    #[Route('/download/{filename}', name: 'app_download')]
    public function download(string $filename): BinaryFileResponse
    {
        $filepath = $this->getParameter('kernel.project_dir') . '/public/files/' . $filename;
        
        $response = new BinaryFileResponse($filepath);
        
        $response->setContentDisposition(
            ResponseHeaderBag::DISPOSITION_ATTACHMENT,
            $filename
        );

        return $response;
    }

    #[Route('/image/{filename}', name: 'app_image')]
    public function image(string $filename): BinaryFileResponse
    {
        $filepath = $this->getParameter('kernel.project_dir') . '/public/images/' . $filename;
        
        $response = new BinaryFileResponse($filepath);
        
        $response->setContentDisposition(
            ResponseHeaderBag::DISPOSITION_INLINE,
            $filename
        );

        return $response;
    }
}

八、总结 #

本章学习了:

  • Request对象获取和使用
  • 获取请求参数(GET/POST/JSON)
  • 文件上传处理
  • 请求头操作
  • Cookie和Session操作
  • Response对象创建
  • 响应状态码和头设置
  • JSON响应
  • 流式响应
  • 文件下载响应

下一章将学习 控制器高级

最后更新:2026-03-28