Пишем первый контроллер на Symfony и работаем с шаблонами
Итак, настроив соединение с базой данных, разобравшись по верхам в структуре папок фреймворка, давайте начнём работать с ним. Первое, с чем я предлагаю вам познакомиться, будет папка с контроллерами, где, как ни странно, и будут находиться наши контроллеры.
Контроллер можно создать вручную, а можно воспользоваться компонентом maker для генерирования контроллера через терминал. Для этого выполните следующую команду в корне проекта (прим.: все команды надо выполнять в корне проекта):
php bin/console make:controller PostsController
Когда вы выполните эту команду, в папке Controller у вас появится класс PostsController.php с одним единственным методом (action) index. Также в папке templates появится папка posts с шаблоном index.html.twig. Использование команд удобно для генерирования простых контроллеров, сущностей, связей между ними, запуска миграций и многого другого.
Когда вы откроете файл PostsController.php, вы увидите, что он наследуется от AbstractController.php. Это базовый контроллер, дающий нам множество полезных методов вроде рендеринга шаблона, редиректа, создания форм и т.д.
В целом наш класс выглядит следующим образом:
<?php
namespace App\Controller;
use Symfony\Bundle\FrameworkBundle\Controller\AbstractController;
use Symfony\Component\Routing\Annotation\Route;
class PostsController extends AbstractController
{
/**
* @Route("/posts", name="posts")
*/
public function index()
{
return $this->render('post/index.html.twig', [
'controller_name' => 'PostsController',
]);
}
}
Что здесь необычного? Например, аннотация над методом index(). Дело в том, что именно так (чаще всего) настраиваются маршруты в Symfony. Route первым аргументом принимает маршрут, он может быть вида /posts, /posts/{id}, где id - плейсхолдер, то есть принимает различные значения. Второй аргумент - это название маршрута. Раньше в ссылках вы привыкли писать полный путь до файла-обработчика, в Symfony вы используете имя маршрута, что обеспечивает код гибкостью, так как независимо от того, где будет находиться файл-обработчик, ссылка всегда будет указывать на него правильно.
Пока наш action рендерит простой базовый шаблон, что не очень интересно. Давайте добавим простой массив данных и попробуем вывести его в шаблоне. Для этого измените ваш код следующим образом:
$posts = [
'post_1' => [
'title' => 'Заголовок первого поста',
'body' => 'Тело первого поста'
],
'post_2' => [
'title' => 'Заголовок второго поста',
'body' => 'Тело второго поста'
]
];
return $this->render('posts/index.html.twig', [
'posts' => $posts,
]);
Передавая данные через шаблон, вы должны помнить, что именно 'posts', а не $posts, шаблонизатор Twig будете видеть в качестве переменной. Таким образом, вы должны давать осмысленное имя и во множественном числе, если работаете с массивом данных.
Перейдите в шаблон templates/posts/index.html.twig. Вы увидите там несложную вёрстку вперемешку со стилями. Удалите всё, что между тегами {% block body %} и {% endblock %}, чтобы ваш файл выглядел так:
{% extends 'base.html.twig' %}
{% block title %} {% endblock %}
{% block body %}
{% endblock %}
Шаблонизатор Twig предлагает всего два типа тегов: {% %} и {{ }}. Первый тег означает, что мы что-то делаем, второй - что-то выводим. Когда мы получаем массив, обычно мы проходимся по нему foreach, чтобы вывести его в понятной форме. В twig нет foreach, но есть цикл for. Чтобы вывести название каждого поста, пройдёмся циклом for так, как это можно делать в twig:
{% for post in posts %}
{{ post.title }}
{% endfor %}
Вы можете обрамлять твиговские теги тегами простого html, например:
<p>{{ post.title }} </p>
Цикл twig выглядит иначе: если в обычном php мы из множественного числа превращаем в единственное (foreach $posts as $post), то тут мы как бы говорим, что для каждого поста в массиве постов (for post in posts) нужно сделать следующее - {{ post.title }}. Через точку мы получаем доступ к ключу ассоциативного массива.
Также в начале файла вы могли заметить следующую строку:
{% extends 'base.html.twig' %}
А вот и главная особенность шаблонизаторов: они позволяют наследоваться друг от друга! Другими словами, в шаблоне base.html.twig вы можете определить нужные стили и javascript скрипты, а также блоки, которые унаследуют все остальные шаблоны. Это удобно, ведь позволяет не писать в каждом шаблоне все ненужные html теги, а сосредоточиться только на выводе информации. В base.html.twig вы могли увидеть блоки {% block title %}, {% block body %} и другие блоки. Глубже с twig мы познакомимся несколько позже, а сейчас вам достаточно знать, что блоки можно переопределять, но писать код нужно только внутри них.
Итак, если вы всё сделали правильно, можете перейти по маршруту /posts и увидеть, что названия двух наших постов вывелись. Таким образом, вы увидели, как работает основной жизненный цикл Symfony: пользователь переходит по конкретному маршруту, который обрабатывает определённый action, он же и отдаёт шаблон с данными для пользователя.
В следующем уроке мы глубже познакомимся с работой контроллеров, создадим первую сущность, наполним базу фейковыми данными, выведем список постов и сделаем красивые ЧПУ по slug!
Комментарии