Symfony 2: Controller

Использование форматов

В настоящее время веб-приложения представляют из себя большее, чем просто HTML странички. Начиная от XML для RSS фидов или веб-сервисов, и заканчивая JSON для Ajax запросов, они имеют множество различных форматов для выбора. Эти форматы полностью поддерживаются Symfony 2.

Давайте настроим маршрут, добавив значение по умолчанию, равное xml для переменной _format.

1
2
3
4
5
6
7
8
9
10
11
12
// src/Acme/DemoBundle/Controller/DemoController.php
use Sensio\Bundle\FrameworkExtraBundle\Configuration\Route;
use Sensio\Bundle\FrameworkExtraBundle\Configuration\Template;
/**
 * @Route("/hello/{name}", defaults={"_format"="xml"}, name="_demo_hello")
 * @Template()
 */
public function helloAction($name)
{
    return array('name' => $name);
}

При использовании формата, Symfony 2 автоматически выбирает правильный шаблон, например в нашем примере это hello.xml.twig:

1
2
3
4
<!-- src/Acme/DemoBundle/Resources/views/Demo/hello.xml.twig -->
<hello>
    <name>{{ name }}</name>
</hello>

Вот и все. Для стандартных форматов Symfony 2 также автоматически выбирает лучший заголовокContent-Type для ответа. Если вы хотите, чтобы одно действие поддерживало различные форматы, используйте плейсхолдер {_format} внутри шаблона маршрута:

1
2
3
4
5
6
7
8
9
10
11
12
// src/Acme/DemoBundle/Controller/DemoController.php
use Sensio\Bundle\FrameworkExtraBundle\Configuration\Route;
use Sensio\Bundle\FrameworkExtraBundle\Configuration\Template;
/**
 * @Route("/hello/{name}.{_format}", defaults={"_format"="html"}, requirements={"_format"="html|xml|json"}, name="_demo_hello")
 * @Template()
 */
public function helloAction($name)
{
    return array('name' => $name);
}

Контроллер будет вызван для URL /demo/hello/Fabien.xml или /demo/hello/Fabien.json

Запись requirements определяет регулярное выражение, которому должен соответствовать плейсхолдер. В этом примере, если вы попытаетесь запросить /demo/hello/Fabien.js, вы получите 404 ошибку HTTP, т.к. запрос не соответствует требованиям формата.

Редиректы и форвардинг

Если вы хотите перенаправить пользователя на другую страницу, используйте метод redirect().

1
return $this->redirect($this->generateUrl('_demo_hello', array('name' => 'Lucas')));

Метод generateUrl() – это метод, схожий с функцией path(), которую мы использовали в шаблонах. Он принимает имя маршрута и массив параметров в качестве аргументов и возвращает сформированный URL.
Также вы можете легко переходить от одного действия к другому с помощью метода forward. Внутренне, Symfony делает подзапрос и возвращает объект ответа (Response) из подзапроса.

1
2
$response = $this->forward('AcmeDemoBundle:Hello:fancy', array('name' => $name, 'color' => 'green'));
// do something with the response or return it directly

Извлечение информации из запроса

Кроме получения значений плейсхолдеров маршрутов, контроллер может получить доступ к объекту ответа (Request):

1
2
3
4
5
6
7
8
9
$request = $this->getRequest();
$request->isXmlHttpRequest(); // is it an Ajax request?
$request->getPreferredLanguage(array('en', 'fr'));
$request->query->get('page'); // get a $_GET parameter
$request->request->get('page'); // get a $_POST parameter

В шаблоне вы также можете получить доступ к объекту запроса (Request) через переменнуюapp.request

1
2
{{ app.request.query.get('page') }}
{{ app.request.parameter('page') }}

Хранение данных в сессии

Несмотря на то, что HTTP – это протокол без сохранения состояния, Symfony 2 предоставляет клиенту (будь то реальный пользователь с браузером, бот или веб-сервис) замечательный объект сессии. Между двумя запросами Symfony 2 хранит данные в куках (cookie), используя нативные сессии PHP. Сохранение в сессию и извлечение данных из сессии легко реализуется в контроллере:

1
2
3
4
5
6
7
8
9
10
$session = $this->getRequest()->getSession();
// store an attribute for reuse during a later user request
$session->set('foo', 'bar');
// in another controller for another request
$foo = $session->get('foo');
// set the user locale
$session->setLocale('fr');

Также вы можете сохранять небольшие сообщения, которые будут доступны только для следующего запроса:

1
2
3
4
5
// store a message for the very next request (in a controller)
$session->setFlash('notice', 'Congratulations, your action succeeded!');
// display the message back in the next request (in a template)
{{ app.session.flash('notice') }}

Это бывает полезно, когда вам нужно установить сообщение об успехе операции до перенаправления пользователя на другую страницу (на которой это сообщение и будет показано).

Безопасность

Symfony Standard Edition поставляется с простой конфигурацией безопасности, которая достаточна в большинстве случаев.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
# app/config/security.yml
security:
    encoders:
        Symfony\Component\Security\Core\User\User: plaintext
    role_hierarchy:
        ROLE_ADMIN:       ROLE_USER
        ROLE_SUPER_ADMIN: [ROLE_USER, ROLE_ADMIN, ROLE_ALLOWED_TO_SWITCH]
    providers:
        in_memory:
            users:
                user:  { password: userpass, roles: [ 'ROLE_USER' ] }
                admin: { password: adminpass, roles: [ 'ROLE_ADMIN' ] }
    firewalls:
        dev:
            pattern:  ^/(_(profiler|wdt)|css|images|js)/
            security: false
        login:
            pattern:  ^/demo/secured/login$
            security: false
        secured_area:
            pattern:    ^/demo/secured/
            form_login:
                check_path: /demo/secured/login_check
                login_path: /demo/secured/login
            logout:
                path:   /demo/secured/logout
                target: /demo/

Данная конфигурация требует авторизации пользователя для всех URL, начинающихся с /demo/secured/ и определяет двух валидных пользователей – user и admin. Кроме того, пользовательadmin обладает ролью ROLE_ADMIN, которая, в свою очередь, включает в себя роль ROLE_USER(взгляните на опцию role_hierarchy).

Для удобочитаемости, в этой простой конфигурации пароли хранятся в виде обычного текста, но вы можете использовать алгоритмы хэширования, настроив секцию encoders.

Перейдя по адресу http://localhost/Symfony/web/app_dev.php/demo/secured/hello вы автоматически будете перенаправлены на форму авторизации, т.к. этот ресурс защищен с помощью файерволла (секция firewalls).
Вы также можете заставить действие требовать данную роль с помощью аннотации @Secure в контроллере:

1
2
3
4
5
6
7
8
9
10
11
12
13
use Sensio\Bundle\FrameworkExtraBundle\Configuration\Route;
use Sensio\Bundle\FrameworkExtraBundle\Configuration\Template;
use JMS\SecurityExtraBundle\Annotation\Secure;
/**
 * @Route("/hello/admin/{name}", name="_demo_secured_hello_admin")
 * @Secure(roles="ROLE_ADMIN")
 * @Template()
 */
public function helloAdminAction($name)
{
    return array('name' => $name);
}

Теперь авторизуйтесь как user (который не обладает ролью ROLE_ADMIN) и со страницы приветствия перейдите по ссылке “Hello resource secured”. Symfony 2 вернет код 403 ошибки протокола HTTP, который показывает, что пользователь не обладает необходимыми привилегиями для доступа к ресурсу.

Слой безопасности в Symfony 2 очень гибкий и поставляется с множеством различных пользовательских провайдеров (например, один для Doctrine ORM) и аутентификационных провайдеров (таких как HTTP basic, HTTP digest, сертификаты X509). Прочитайте главуБезопасность для получения полной информации о том, как используется и настраивается безопасность в Symfony 2.

Кэширование ресурсов

Как только ваш сайт начнет генерировать больше трафика, вы захотите избавиться от необходимости генерировать какой-либо ресурс снова и снова раз за разом. Symfony 2 использует заголовки HTTP кэша для управления кэшем ресурсов. Для простой стратегии кэширования используется удобная аннотация @Cache():

1
2
3
4
5
6
7
8
9
10
11
12
13
use Sensio\Bundle\FrameworkExtraBundle\Configuration\Route;
use Sensio\Bundle\FrameworkExtraBundle\Configuration\Template;
use Sensio\Bundle\FrameworkExtraBundle\Configuration\Cache;
/**
 * @Route("/hello/{name}", name="_demo_hello")
 * @Template()
 * @Cache(maxage="86400")
 */
public function helloAction($name)
{
    return array('name' => $name);
}

В этом примере ресурс будет закэширован на одни сутки. Но вы можете использовать валидацию вместо истечения, или комбинацию двух способов, если вам это необходимо. Кэшированием ресурсов управляет встроенный в Symfony 2 обратный прокси (reverse proxy). Но так как кэшированием управляют обычные кэширующие HTTP заголовки, вы можете заменить встроенный обратный прокси наVarnish или Squid и легко масштабировать ваше приложение.

Но что если вы не хотите кэшировать страницы целиком? Symfony 2 решает эту проблему с помощью Edge Side Includes (ESI), поддерживаемый непосредственно. Узнайте больше, прочитав главу HTTP кэш

скопировано с http://trish.in/article/symfony-2-controller

Advertisements

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out / Change )

Twitter picture

You are commenting using your Twitter account. Log Out / Change )

Facebook photo

You are commenting using your Facebook account. Log Out / Change )

Google+ photo

You are commenting using your Google+ account. Log Out / Change )

Connecting to %s

%d bloggers like this: