Когда вы загружаете стандартный дистрибутив 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.yml
blog_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
Теперь вы можете одним взглядом проверить, какое действие вызывается из шаблона маршрута.
Если вы хотите, чтобы все ваши действия из контроллера имели префикс, например /admin
prefix
routing.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" }
* )
*/
Добавляя slug
defaults
{slug}
URL /article
slug
hello
URL /blog/world
world
Добавление требований
Синтаксис: 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" }
* )
*/
Мы также можем сопоставить метод входящего запроса (например, GET
POST
PUT
DELETE
Помните, что если метод не указан, маршрут будет соответствовать любому из них.
Применение схемы 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) { /* ... */ }
}
Последние мысли
Как видите, управление маршрутами с аннотациями легко и просто, а также легко читать и обслуживать. Он также обладает хорошим преимуществом сбора кода и конфигурации в уникальный файл: класс контроллера.
Используете ли вы аннотации или стандартную конфигурацию? Что вы предпочитаете и почему?