Ответ
Symfony не реализует PSR-7 (HTTP Message Interfaces) нативно в своем ядре. Вместо этого он использует собственный, более ранний и функционально богатый компонент HttpFoundation.
Почему Symfony выбрал этот путь:
- Исторические причины: Компонент
HttpFoundationбыл создан и стабилизирован задолго до принятия PSR-7. Переписать весь фреймворк и экосистему бандлов под новый стандарт был бы крайне затратным. - Различия в философии: PSR-7 требует, чтобы объекты запроса и ответа были иммутабельными (неизменяемыми). Это хорошо для middleware-архитектуры, но может быть менее удобно и немного медленнее для традиционного MVC, где объекты запроса часто модифицируются (например, добавляются атрибуты). Объекты Symfony
RequestиResponse— мутабельны. - Удобство API:
HttpFoundationпредоставляет множество удобных методов "из коробки" для работы с сессиями, файлами, локалями, которые в PSR-7 потребовали бы дополнительных библиотек.
Пример работы с Symfony Request:
use SymfonyComponentHttpFoundationRequest;
use SymfonyComponentHttpFoundationJsonResponse;
// Request создается из глобальных переменных
$request = Request::createFromGlobals();
// Удобный доступ к данным
$id = $request->query->get('id'); // GET-параметр
$content = $request->request->get('name'); // POST-параметр
$file = $request->files->get('avatar'); // Загруженный файл
$header = $request->headers->get('Authorization');
// Мутабельность: можно добавить атрибут для передачи данных во внутренние слои
$request->attributes->set('_controller', 'AppControllerApiController::show');
// Ответ также прост
$response = new JsonResponse(['status' => 'success', 'id' => $id]);
$response->setStatusCode(201);
$response->headers->set('Cache-Control', 'no-cache');
Совместимость с PSR-7: Несмотря на это, Symfony обеспечивает полную совместимость через отдельные компоненты. Если вам нужно работать с библиотекой, требующей PSR-7 (например, многие PSR-15 middleware), вы можете использовать:
symfony/psr-http-message-bridge: Конвертирует объектыHttpFoundationв PSR-7 и обратно.nyholm/psr7: Легковесная и быстрая реализация PSR-7, рекомендованная для использования с Symfony.
Таким образом, вы можете разрабатывать приложение на привычном HttpFoundation, а на уровне контроллера или при интеграции с внешними компонентами легко конвертировать запросы и ответы.
Ответ 18+ 🔞
А, ну это классика, блядь! Сейчас объясню на пальцах, почему у Симфони своя атмосфера, а не этот ваш PSR-7.
Представь себе: есть старый, проверенный дедовский HttpFoundation. Он появился, когда про PSR-7 ещё и в проекте не было, ёпта. И он работал, работает и будет работать — удобный, как родной тапок. А потом приходят эти умники с PSR-7 и говорят: «А давайте сделаем всё иммутабельным!». То есть, раз создал объект запроса — иди нахуй, больше его не трогай. Хочешь что-то изменить — создавай новый, целый, блядь, объект.
Ну и кому это надо в обычном-то MVC, я спрашиваю? У меня в контроллере часто нужно в запрос какой-нибудь атрибут воткнуть, чтобы потом в сервисе его вытащить. А по PSR-7 — хуй там, а не атрибут. Придётся новый объект городить. Это ж какая писанина, мать его! И производительность подумай — копировать целый объект вместо того, чтобы одно поле поменять.
Вот Симфони и не стала ломать свою огромную экосистему и переписывать всё под эту моду. Зачем, если своя бандура и так огонь? Смотри, как просто:
use SymfonyComponentHttpFoundationRequest;
use SymfonyComponentHttpFoundationJsonResponse;
// Всё из глобальных переменных само натягивается — красота!
$request = Request::createFromGlobals();
// Достаём данные — элементарно, Ватсон!
$id = $request->query->get('id'); // Гет-параметр
$name = $request->request->get('name'); // Пост-параметр
$file = $request->files->get('avatar'); // Файл, ёбана!
$header = $request->headers->get('Authorization'); // Заголовок
// А вот и фишка — мутабельность! Подкинул атрибут и пошёл дальше.
$request->attributes->set('_controller', 'AppControllerApiController::show');
// Ответ — тоже не надо мозги выебывать.
$response = new JsonResponse(['status' => 'success', 'id' => $id]);
$response->setStatusCode(201); // Меняем статус когда захотим
$response->headers->set('Cache-Control', 'no-cache'); // И заголовки тоже
Прямо как живой, всё под рукой, ни одной лишней телодвижения. Удобство — овердохуища!
Но! Если вдруг тебе надо именно PSR-7 (какой-нибудь внешний middleware упоротый требует), то Симфони не бросит в беде. Есть мосты, ёпта!
Поставишь symfony/psr-http-message-bridge — и он будет как переводчик между твоим родным HttpFoundation и этим стерильным PSR-7. Сделал запрос по-старому, конвертнул в PSR-7, отдал в чужую библиотеку, получил ответ — и обратно конвертнул в родной формат. Всё прозрачно.
А для скорости ещё и nyholm/psr7 посоветуют — лёгкая реализация, без этих ваших наворотов.
Короче, суть: Симфони не использует PSR-7, потому что у неё есть свой, более удобный и исторически сложившийся инструмент. Но если очень приспичит — всегда можно натянуть совместимость, без проблем. Не парься.