Вы все еще с нами после первых двух частей? Да вы уже ярый приверженец 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). Но это уже тема для нашего следующего разговора!
3 Comments
Тестировал на symphony 2.0-RC2. Форматы не заработали…
Насколько я вижу статья про форматы не изменялась. Хотя мало ли – тогда был preview релиз, а сейчас уже release candidate.
Заработают, если обратить внимание на:
pattern: /hello/:name.:_format