Вы все еще с нами после первых двух частей? Да вы уже ярый приверженец Symfony )) Давайте же без лишней суеты в третьей части разберем, что же для вас может сделать контроллер.
- Symfony 2.0 – быстрый тур – общая картинка (часть 1)
- Symfony 2.0 – быстрый тур – вид/the view (часть 2)
- Symfony 2.0 – быстрый тур – пакеты/the bundles (часть 4)
- Symfony 2.0 – быстрый тур – архитектура/the architecture (часть 5)
Форматы / Formats
Современное web-приложение должно доставлять пользователю больше чем просто HTML-страницы. Тип контента может варьироваться от XML для RSS ил web-сервисов до JSON для Ajax-запросов. Есть множество различных форматов на любой вкус и случай жизни. Symfony имеет встроенную поддержку этих форматов. Отредактируйте routing.yml
и добавьте _format
создначением xml:
# src/Application/HelloBundle/Resources/config/routing.yml hello: pattern: /hello/:name defaults: { _bundle: HelloBundle, _controller: Hello, _action: index, _format: xml }
Затем, добавьте шаблон index.xml.php
рядом с index.php
:
# src/Application/HelloBundle/Resources/views/Hello/index.xml.php <hello> <name><?php echo $name ?></name> </hello>
Вот и все что нужно сделать. Не требуется даже менять контроллер. Для стандартных форматов Symfony автоматически выберет лучший заголовок content-type
для ответа. Если вы хотите поддерживать различные форматы в одном действии (action), используйте :_format
в настройке маршрута:
# src/Application/HelloBundle/Resources/config/routing.yml hello: pattern: /hello/:name.:_format defaults: { _bundle: HelloBundle, _controller: Hello, _action: index, _format: html } requirements: { _format: (html|xml|json) }
Контроллер теперь будет вызываться для URL вида: /hello/Fabien.xml
или для /hello/Fabien.json
. В качестве значения по умолчанию для _format
используется html, /hello/Fabien
и /hello/Fabien.html
оба используют HTML формат.
Требования (requirements
) определяют регулярное выражение, которому переменная для подстановки (placeholder) должна соответствовать. В этом примере, если вы захотите вызвать /hello/Fabien.js
вы получите ошибку HTTP 404, так как запрос не соответствует требованиям маршрута.
Объект ответа / The Response Object
Давайте теперь вернемся к контроллеру Hello:
public function indexAction($name) { return $this->render('HelloBundle:Hello:index', array('name' => $name)); }
Метод render() осуществляет отображение шаблона и возвращает объект Response. Ответ сервера может быть донастроен перед его отправкой клиенту, например, можно изменить Content-type:
public function indexAction($name) { $response = $this->render('HelloBundle:Hello:index', array('name' => $name)); $response->setHeader('Content-Type', 'text/plain'); return $response; }
Для простейших шаблонов вы даже можете создавать объект Response вручную и сэкономить этим несколько милисекунд:
public function indexAction($name) { return $this->createResponse('Hello '.$name); }
Чаще всего это имеет смыл применять, например, для JSON-содержимого, что, в свою очередь, может быть использовано для Ajax-запросов.
Управление ошибками / Error Management
Когда что-то не может быть найдено, вы должны вернуть ошибку 404. Это легко сделать, вызвав специальное HTTP исключение:
use SymfonyComponentsRequestHandlerExceptionNotFoundHttpException; public function indexAction() { $product = // retrieve the object from database if (!$product) { throw new NotFoundHttpException('The product does not exist.'); } return $this->render(...); }
NotFoundHttpException
вернет в браузер ответ с ошибкой 404. Похожим образом действует и исключение ForbiddenHttpException
, которое возвращает ошибку 403 и UnauthorizedHttpException
, которое возвращает ошибку 401. Для других кодов ошибок вы можете использовать базовый класс HttpException
и передавать код ошибки в качестве кода исключения:
throw new HttpException('Unauthorized access.', 401);
Перемещения и перенаправления / Redirecting and Forwarding
Если вы хотите переместить пользователя на другую страницу, вы можете использовать метод redirect().
$this->redirect($this->generateUrl('hello', array('name' => 'Lucas')));
Метод generateUrl здесь – это такой же метод, как и generate(), который мы использовали в хелпере маршрутизации ранее. Он принимает в качестве аргументов наименование маршрутов и массив параметров, на основе чего возвращает дружественный URL. Вы также легко можете перенаправить одно действие на другое при помощи метода forward(). Как и хелпер $view-actions, он выполняет внутренний подзапрос, но он возвращает объект Response, который при необходимости можно изменять:
$response = $this->forward('HelloBundle:Hello:fancy', array('name' => $name, 'color' => 'green')); // do something with the response or return it directly
Объект запроса / The Request Object
Кроме значений подстановки (placeholders) из маршрутов, контроллер также имеет доступ к объекту запроса Request:
$request = $this->getRequest(); $request->isXmlHttpRequest(); // is it an Ajax request? $request->getPreferredLanguage(array('en', 'fr')); $request->getQueryParameter('page'); // get a $_GET parameter $request->getRequestParameter('page'); // get a $_POST parameter
В шаблоне вы также можете получить доступ к объекту запроса через хелпер request:
<?php echo $view->request->getParameter('page') ?>
Последний рывок / Final Thoughts
Вот и все, что хотелось рассказать, и я даже не уверен, что мы использовали все 10 минут )) В предыдущей части мы видели, как можно расширить систему шаблонов при помощи хелперов. Расширение возможностей контроллеров может быть легко достигнуто благодаря пакетам (bundles). Но это уже тема для нашего следующего разговора!
Тестировал на symphony 2.0-RC2. Форматы не заработали…
Насколько я вижу статья про форматы не изменялась. Хотя мало ли – тогда был preview релиз, а сейчас уже release candidate.
Заработают, если обратить внимание на:
pattern: /hello/:name.:_format