in Профессиональное

Symfony 2.0 – быстрый тур – контроллер/the controller (часть 3)

Вы все еще с нами после первых двух частей? Да вы уже ярый приверженец Symfony )) Давайте же без лишней суеты в третьей части разберем, что же для вас может сделать контроллер.

Форматы / 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). Но это уже тема для нашего следующего разговора!

Оригинал: http://symfony-reloaded.org/quick-tour-part-3

Write a Comment

Comment

*

  1. Тестировал на symphony 2.0-RC2. Форматы не заработали…

    • Насколько я вижу статья про форматы не изменялась. Хотя мало ли – тогда был preview релиз, а сейчас уже release candidate.