Статьи

Начало работы с аннотациями маршрутов Symfony2

Когда вы загружаете стандартный дистрибутив Symfony 2 , он включает в себя интересный пакет под названием SensioFrameworkExtraBundle, который реализует много полезных вещей, особенно возможность использовать аннотации непосредственно в ваших контроллерах.

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

В Symfony 2 реализован мощный встроенный компонент для управления всеми маршрутами приложения: компонент маршрутизации. По сути, маршрут отображает URL на действие контроллера. Поскольку Symfony должен быть модульным, для него выделен файл: routing.yml . Вы найдете это в app > config > routing.yml

Чтобы понять, как определять наши маршруты с аннотациями, я возьму в качестве примера простое приложение для блога.

Шаг 1: создание маршрута домашней страницы

Мы просто хотим связать путь /HomeController

Без аннотаций

В app/config/routing.yml

 blog_front_homepage:
  path : /
  defaults:  { _controller: BlogFrontBundle:Home:index }

В src/Blog/FrontBundle/Controller/HomeController.php

 <?php
namespace Blog\FrontBundle\Controller;

class HomeController
{
    public function indexAction()
    {
        //... create and return a Response object
    } 
}

Давайте посмотрим на эти файлы. В routing.ymlblog_front_homepage Что касается контроллера, ему не нужно ничего особенного.

С аннотациями

В app/config/routing.yml

 blog_front:
    resource: "@BlogFrontBundle/Controller/"
    type:     annotation
    prefix:   /

В src/Blog/FrontBundle/Controller/HomeController.php

 <?php

namespace Blog\FrontBundle\Controller;
use Sensio\Bundle\FrameworkExtraBundle\Configuration\Route;

class HomeController
{
    /**
     * @Route("/", name="blog_home_index")
     */
    public function indexAction() { /* ... */ }
}

Для начала посмотрим, что случилось с routing.yml

  • resource
  • type
  • prefix

Что еще интереснее, так это то, как теперь построен наш контроллер. Прежде всего, мы должны вызвать соответствующий класс SensioFrameworkExtraBundle: use Sensio\Bundle\FrameworkExtraBundle\Configuration\Route; , Теперь мы готовы реализовать маршрут и параметры, которые мы хотим назначить: в этом случае только путь и имя (позже мы увидим все, что мы можем сделать): @Route("/", name="blog_homepage")

Некоторые из вас могут подумать: «Ну, мы знаем, как переопределить контроллер с уровнем маршрутизации, и что? В конце концов, для того же результата требуется больше кода ». И ты был бы прав … По крайней мере, пока.

Шаг 2: добавление маршрута на страницу статьи

Без аннотаций

В app/config/routing.yml

 blog_front_homepage:
  path : /
  defaults:  { _controller: BlogFrontBundle:Home:index }

blog_front_article:
  path : /article/{slug}
  defaults:  { _controller: BlogFrontBundle:Home:showArticle }

В src/Blog/FrontBundle/Controller/HomeController.php

 <?php
// namespace & uses...

class HomeController
{
    public function indexAction() { /* ... */ }
    
    public function showArticleAction($slug) { /* ... */ }
}

С аннотациями

В app/config/routing.yml

 blog_front:
    resource: "@BlogFrontBundle/Controller/"
    type:     annotation
    prefix:   /

В src/Blog/FrontBundle/Controller/HomeController.php

 <?php
// namespace & uses...

class HomeController
{
    /**
     * @Route("/", name="blog_home_index")
     */
    public function indexAction() { /* ... */ }
    
    /**
     * @Route("/article/{slug}", name="blog_home_show_article")
     */
    public function showArticleAction($slug) { /* ... */ }
}

Вы заметили? routing.yml Теперь вы можете одним взглядом проверить, какое действие вызывается из шаблона маршрута.

Если вы хотите, чтобы все ваши действия из контроллера имели префикс, например /adminprefixrouting.yml@Route

В app/config/routing.yml

 blog_front: ...
 
blog_admin:
    resource: "@BlogAdminBundle/Controller/"
    type:     annotation

В src/Blog/AdminBundle/Controller/AdminController.php

 <?php
// namespace & uses...

/**
 * @Route("/admin")
 */
class AdminController
{
    /**
     * @Route("/", name="blog_admin_index")
     */
    public function indexAction() { /* ... */ }
    
    /**
     * @Route("/create", name="blog_admin_create_article")
     */
    public function createArticleAction() { /* ... */ }
}

Шаг 3: дополнительная настройка маршрутизации

Настройка параметров URL по умолчанию

Синтаксис: defaults = { "key" = "value" }

 /**
 * @Route(
 *       path     = "/article/{slug}",
 *       name     = "blog_home_show_article",
 *       defaults = { "slug" = "hello" }
 * )
 */

Добавляя slugdefaults{slug} URL /articleslughello URL /blog/worldworld

Добавление требований

Синтаксис: requirements = { "key" = "value" }

 /**
 * @Route(
 *       path         = "/article/{slug}",
 *       name         = "blog_home_show_article",
 *       defaults     = { "slug" = "hello" },
 *       requirements = { "slug" = "[a-z]+" }
 * )
 */

Мы можем определить требования для ключа slug{slug} В следующем примере мы делаем то же самое с цифрами:

 /**
 * @Route(
 *       path         = "article/{id}",
 *       name         = "blog_home_show_article",
 *       defaults     = { "id" = 1 },
 *       requirements = { "id" = "\d+" } 
 * )
 */

Если вам нужна дополнительная информация о регулярных выражениях, перейдите по этой ссылке .

Применение метода HTTP

Синтаксис: methods = { "request method" }

 /**
 * @Route(
 *       path         = "/article/{slug}",
 *       name         = "blog_home_show_article",
 *       defaults     = { "slug" = "hello" },
 *       requirements = { "slug" = "[a-z]+" },
 *       methods      = { "GET", "POST" }
 * )
 */

Мы также можем сопоставить метод входящего запроса (например, GETPOSTPUTDELETE Помните, что если метод не указан, маршрут будет соответствовать любому из них.

Применение схемы HTTP

Синтаксис: schemes = { "protocol" }

 /**
 * @Route(
 *       path         = "/article/{slug}",
 *       name         = "blog_home_show_article",
 *       defaults     = { "slug" = "hello" },
 *       requirements = { "slug" = "[a-z]+" },
 *       methods      = { "GET", "POST" },
 *       schemes      = { "https" }  
 * )
 */

В этом случае мы хотим защитить маршрут, чтобы быть уверенным, что к нему осуществляется доступ по протоколу HTTPS.

Применение имени хоста

Синтаксис: host = "myhost.com"

 /**
 * @Route(
 *       path         = "/article/{slug}",
 *       name         = "blog_home_show_article",
 *       defaults     = { "slug" = "hello" },
 *       requirements = { "slug" = "[a-z]+" },
 *       methods      = { "GET", "POST" },
 *       schemes      = { "https" },
 *       host         = "myblog.com"
 * )
 */

Мы также можем сопоставить на HTTP-хосте. Этот будет соответствовать только если хост myblog.com

Шаг 4: упражнение

Теперь, когда мы можем построить надежную структуру маршрутизации, представьте, что нам нужно создать действие для удаления статьи с правильным маршрутом в нашем AdminController.php Мы должны:

  • Определите путь как /admin/delete/article/{id}
  • Определите имя как blog_admin_delete_article
  • Определите требование для id
  • Определите метод запроса GET

Застрял? Посмотрите на решение ниже:

 <?php
// src/Blog/AdminBundle/Controller/AdminController.php
// namespace & uses...

/**
 * @Route("/admin")
 */
class AdminController
{
    /* ... */

    /**
     * @Route("
     *    path          = "/delete/article/{id}", 
     *    name          = "blog_admin_delete_article"
     *    requirements  = { "id" = "\d+" },
     *    methods       = { "GET" }
     * )
     */
    public function deleteArticleAction($id) { /* ... */ }
}

Последние мысли

Как видите, управление маршрутами с аннотациями легко и просто, а также легко читать и обслуживать. Он также обладает хорошим преимуществом сбора кода и конфигурации в уникальный файл: класс контроллера.

Используете ли вы аннотации или стандартную конфигурацию? Что вы предпочитаете и почему?