Skip to content
  • About
    • What is Symfony?
    • Community
    • News
    • Contributing
    • Support
  • Documentation
    • Symfony Docs
    • Symfony Book
    • Screencasts
    • Symfony Bundles
    • Symfony Cloud
    • Training
  • Services
    • Platform.sh for Symfony Best platform to deploy Symfony apps
    • SymfonyInsight Automatic quality checks for your apps
    • Symfony Certification Prove your knowledge and boost your career
    • SensioLabs Professional services to help you with Symfony
    • Blackfire Profile and monitor performance of your apps
  • Other
  • Blog
  • Download
sponsored by
  1. Home
  2. Documentation
  3. Symfony: The Fast Track
  4. Russian
  5. Создание контроллера

Создание контроллера

Наш проект гостевой книги уже работает в продакшене, однако мы немного схитрили. У проекта пока ещё нет ни одной веб-страницы, а на главной странице по-прежнему отображается ошибка 404. Давайте исправим это.

Когда приходит HTTP-запрос, например, на главную страницу (http://localhost:8000/), Symfony пытается найти маршрут , соответствующий пути запроса (/ в данном случае). Маршрут — это связующее звено между путём запроса и callback-функцией PHP, которая создаёт ответ HTTP для этого запроса.

Эти callback-функции PHP называются "контроллерами". В Symfony большинство контроллеров реализовано в виде PHP-классов. Конечно, вы можете вручную создать такой класс, но для быстроты разработки давайте посмотрим, как Symfony в этом может нам помочь.

Ускорение разработки с помощью бандла Maker

Для лёгкой генерации контроллеров мы можем использовать пакет symfony/maker-bundle, который был установлен как часть пакета webapp.

Бандл Maker поможет вам сгенерировать множество различных классов. Мы будем использовать его на протяжении всей книги. Каждый "генератор" определён в отдельной команде, при этом все команды принадлежат одному и тому же пространству имён команды make.

Компонент Symfony Console имеет встроенную команду list, которая выводит список всех команд в указанном пространстве имен; используйте её, чтобы посмотреть все доступные генераторы бандла Maker:

1
$ symfony console list make

Выбор формата конфигурации

Перед созданием нашего первого контроллера в проекте, нам необходимо определиться с используемыми форматами для написания конфигураций. По умолчанию Symfony поддерживает YAML, XML, PHP и PHP-атрибуты.

YAML идеален для конфигурации пакетов. Этот формат будет использоваться в файлах директории config/. Зачастую, когда вы устанавливаете новый пакет, рецепт этого пакета добавляет новый файл с расширением .yaml в эту директорию.

Для конфигурации, связанной с PHP-кодом, лучше всего подойдут атрибуты, поскольку они указываются рядом с кодом. Сейчас объясню на примере. Когда приходит запрос, определённая конфигурация должна передать Symfony, что текущий путь запроса должен обрабатываться соответствующим контроллером (то есть PHP-классом). При использовании конфигурационных форматов на YAML, XML или PHP потребуется включать два файла (сам конфигурационный файл и PHP-файл контроллера). В то же время с помощью атрибутов можно всё сконфигурировать непосредственно в самом классе контроллера.

Вам может быть интересно узнать, какой именно пакет нужно установить, чтобы добавить поддержку той или иной функциональной возможности? Как правило, вам не нужно этого знать. Поскольку в большинстве случаев Symfony показывает отсутствующий пакет в сообщении об ошибке. К примеру, выполнение команды symfony make:message без установленного пакета messenger выбросит исключение с подсказкой о том, какой пакет следует установить.

Генерация контроллера

Создайте свой первый контроллер с помощью команды make:controller:

1
$ symfony console make:controller ConferenceController

Команда создает класс ConferenceController в директории src/Controller/. Сгенерированный класс содержит немного шаблонного кода, который может быть изменён:

src/Controller/ConferenceController.php
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
namespace App\Controller;

use Symfony\Bundle\FrameworkBundle\Controller\AbstractController;
use Symfony\Component\HttpFoundation\Response;
use Symfony\Component\Routing\Annotation\Route;

class ConferenceController extends AbstractController
{
    #[Route('/conference', name: 'conference')]
    public function index(): Response
    {
        return $this->render('conference/index.html.twig', [
            'controller_name' => 'ConferenceController',
        ]);
    }
}

С помощью атрибута #[Route('/conference', name: 'conference')] метод index() становится контроллером (его объявление вместе с конфигурацией находится непосредственно над кодом).

При переходе в браузере по пути /conference выполняется контроллер, который возвращает HTTP-ответ.

Настройте маршрут так, чтобы он соответствовал главной странице:

1
2
3
4
5
6
7
8
9
10
11
--- a/src/Controller/ConferenceController.php
+++ b/src/Controller/ConferenceController.php
@@ -8,7 +8,7 @@ use Symfony\Component\Routing\Annotation\Route;

 class ConferenceController extends AbstractController
 {
-    #[Route('/conference', name: 'conference')]
+    #[Route('/', name: 'homepage')]
     public function index(): Response
     {
         return $this->render('conference/index.html.twig', [

Параметр маршрута name пригодится нам, когда понадобится получить ссылку на главную страницу. Таким образом, вместо жёстко заданного в коде пути /, мы будем использовать имя маршрута.

Теперь вернём обычный HTML-код вместо шаблона по умолчанию:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
--- a/src/Controller/ConferenceController.php
+++ b/src/Controller/ConferenceController.php
@@ -11,8 +11,13 @@ class ConferenceController extends AbstractController
     #[Route('/', name: 'homepage')]
     public function index(): Response
     {
-        return $this->render('conference/index.html.twig', [
-            'controller_name' => 'ConferenceController',
-        ]);
+        return new Response(<<<EOF
+<html>
+    <body>
+        <img src="/images/under-construction.gif" />
+    </body>
+</html>
+EOF
+        );
     }
 }

Перезагрузите главную страницу в браузере:

/

Основная задача контроллера — вернуть объект Response в качестве ответа на HTTP-запрос.

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

1
2
$ git add .
$ git commit -m'Add the index controller'

Добавление пасхального яйца

Для демонстрации того, как в ответе можно использовать информацию из запроса, давайте добавим небольшое пасхальное яйцо. При переходе на главную страницу, если в строке запроса мы находим что-то типа ?hello=Fabien, то показываем приветственное сообщение.

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
--- a/src/Controller/ConferenceController.php
+++ b/src/Controller/ConferenceController.php
@@ -3,17 +3,24 @@
 namespace App\Controller;

 use Symfony\Bundle\FrameworkBundle\Controller\AbstractController;
+use Symfony\Component\HttpFoundation\Request;
 use Symfony\Component\HttpFoundation\Response;
 use Symfony\Component\Routing\Annotation\Route;

 class ConferenceController extends AbstractController
 {
     #[Route('/', name: 'homepage')]
-    public function index(): Response
+    public function index(Request $request): Response
     {
+        $greet = '';
+        if ($name = $request->query->get('hello')) {
+            $greet = sprintf('<h1>Hello %s!</h1>', htmlspecialchars($name));
+        }
+
         return new Response(<<<EOF
 <html>
     <body>
+        $greet
         <img src="/images/under-construction.gif" />
     </body>
 </html>

Посмотреть данные запроса в Symfony можно через объект Request. Если в объявлении типа для аргумента контроллера указать объект запроса, Symfony автоматически передаст его вам. Далее используем этот объект, чтобы получить параметр name из строки запроса и добавляем его в заголовок <h1>.

Чтобы увидеть получившийся результат, сначала в браузере перейдите на главную страницу (/), а после по пути /?hello=Fabien.

Note

Обратите внимание на вызов функции htmlspecialchars(), который нужен, чтобы защититься от XSS-атак. Когда мы начнём использовать шаблонизатор, он автоматически защитит нас от подобных проблем с безопасностью.

Также отмечу, что имя можно сделать частью URL-адреса:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
--- a/src/Controller/ConferenceController.php
+++ b/src/Controller/ConferenceController.php
@@ -9,11 +9,11 @@ use Symfony\Component\Routing\Annotation\Route;

 class ConferenceController extends AbstractController
 {
-    #[Route('/', name: 'homepage')]
-    public function index(Request $request): Response
+    #[Route('/hello/{name}', name: 'homepage')]
+    public function index(string $name = ''): Response
     {
         $greet = '';
-        if ($name = $request->query->get('hello')) {
+        if ($name) {
             $greet = sprintf('<h1>Hello %s!</h1>', htmlspecialchars($name));
         }

Составная часть маршрута {name} — это динамический параметр маршрута. Он работает так же, как и знак подстановки. Теперь можно перейти в браузере по пути /hello, а затем на /hello/Fabien — результат будет одинаковый. Значение параметра {name} можно получить, добавив имя аргумента в контроллер (то есть $name).

Отмените изменения, которые мы только что внесли:

1
$ git checkout src/Controller/ConferenceController.php
1
2
$ git reset HEAD src/Controller/ConferenceController.php
$ git checkout src/Controller/ConferenceController.php

Отладочные переменные

Отличным помощником в отладке является функция Symfony dump(). Она всегда доступна и позволяет отображать сложные переменные в красивом интерактивном формате.

Временно измените src/Controller/ConferenceController.php для отображения объекта Request:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
--- a/src/Controller/ConferenceController.php
+++ b/src/Controller/ConferenceController.php
@@ -3,14 +3,17 @@
 namespace App\Controller;

 use Symfony\Bundle\FrameworkBundle\Controller\AbstractController;
+use Symfony\Component\HttpFoundation\Request;
 use Symfony\Component\HttpFoundation\Response;
 use Symfony\Component\Routing\Annotation\Route;

 class ConferenceController extends AbstractController
 {
     #[Route('/', name: 'homepage')]
-    public function index(): Response
+    public function index(Request $request): Response
     {
+        dump($request);
+
         return new Response(<<<EOF
 <html>
     <body>

При обновлении страницы обратите внимание на новый значок "target" на панели инструментов; он позволяет осмотреть дамп. Щёлкните по нему, чтобы перейти на детальную страницу, где навигация упрощена:

/

Отмените изменения, которые мы только что внесли:

1
$ git checkout src/Controller/ConferenceController.php
1
2
$ git reset HEAD src/Controller/ConferenceController.php
$ git checkout src/Controller/ConferenceController.php

Двигаемся дальше

  • Система маршрутизации в Symfony;
  • Обучающий видеоролик по маршрутам, контроллерам и страницам на SymfonyCasts;
  • Атрибуты PHP;
  • Компонент HttpFoundation;
  • Методика атаки через межсайтовый скриптинг (Cross-Site Scripting или XSS);
  • Шпаргалка по маршрутизации в Symfony.
Previous page Поиск и устранение неисправностей
Next page Подготовка базы данных
This work, including the code samples, is licensed under a Creative Commons BY-NC-SA 4.0 license.
TOC
    Version

    Symfony 5.4 is backed by

    Symfony Code Performance Profiling

    Symfony Code Performance Profiling

    Save your teams and projects before they sink

    Save your teams and projects before they sink

    Version:
    Locale:
    ebook

    This book is backed by:

    see all backers

    Symfony footer

    Avatar of Ilia Lazarev, a Symfony contributor

    Thanks Ilia Lazarev (@ilzrv) for being a Symfony contributor

    1 commit • 2 lines changed

    View all contributors that help us make Symfony

    Become a Symfony contributor

    Be an active part of the community and contribute ideas, code and bug fixes. Both experts and newcomers are welcome.

    Learn how to contribute

    Symfony™ is a trademark of Symfony SAS. All rights reserved.

    • What is Symfony?

      • What is Symfony?
      • Symfony at a Glance
      • Symfony Components
      • Symfony Releases
      • Security Policy
      • Logo & Screenshots
      • Trademark & Licenses
      • symfony1 Legacy
    • Learn Symfony

      • Symfony Docs
      • Symfony Book
      • Reference
      • Bundles
      • Best Practices
      • Training
      • eLearning Platform
      • Certification
    • Screencasts

      • Learn Symfony
      • Learn PHP
      • Learn JavaScript
      • Learn Drupal
      • Learn RESTful APIs
    • Community

      • Symfony Community
      • SymfonyConnect
      • Events & Meetups
      • Projects using Symfony
      • Contributors
      • Symfony Jobs
      • Backers
      • Code of Conduct
      • Downloads Stats
      • Support
    • Blog

      • All Blog Posts
      • A Week of Symfony
      • Case Studies
      • Cloud
      • Community
      • Conferences
      • Diversity
      • Living on the edge
      • Releases
      • Security Advisories
      • Symfony Insight
      • Twig
      • SensioLabs Blog
    • Services

      • SensioLabs services
      • Train developers
      • Manage your project quality
      • Improve your project performance
      • Host Symfony projects

      Powered by

    Follow Symfony