Введение в symfony
Пакеты и зависимости
apk add php83-iconv php83-ctype php83-tokenizer php83-simplexml php83-dom composer
#Установка symfony symfony-CLI для Alpine:
sudo apk add --no-cache bash
curl -1sLf 'https://dl.cloudsmith.io/public/symfony/stable/setup.alpine.sh' | sudo -E bash
sudo apk add symfony-cli
#который предоставляет все инструменты, необходимые для разработки и локального запуска приложения Symfony
#Двоичный файл symfony также предоставляет инструмент для проверки соответствия окружения всем требованиям:
symfony check:requirements
#Создать веб-проект
composer create-project symfony/skeleton /var/www/test.netbash
#Если вы хотите использовать LTS-версию, добавьте параметр --version
composer create-project symfony/skeleton --version=lts /var/www/test.netbash
cd project
composer require webapp
#Информация о проекте
php bin/console about
#Запуск локального веб-сервера
symfony server:start
#Чтобы добавить в приложение функции отладки, можно запустить команду composer require --dev debug . Это установит symfony/debug-pack, который, в свою очередь, установит несколько пакетов, таких как symfony/debug-bundle, symfony/monolog-bundle, symfony/var-dumper, и т. д. composer require --dev debug
#Проверка уязвимостей
symfony check:security
#Или
composer audit
#Вспомогательные команды для отладки
php bin/console
#Список всех маршрутов
php bin/console debug:router
#Панель инструментов веб-отладки symfony/profiler-pack
composer require symfony/profiler-pack
#Рендеринг шаблона
#В Symfony есть Twig: минималистичный, мощный и довольно интересный язык шаблонов
#Установка
composer require twig
config/
Содержит... конфигурацию, маршруты, сервисы и пакеты.
src/
Здесь находится весь ваш PHP-код.
templates/
Здесь хранятся все ваши шаблоны Twig.
bin/
Здесь находится файл bin/console (а также другие, менее важные исполняемые файлы).
var/
Здесь хранятся автоматически создаваемые файлы, такие как файлы кэша (var/cache/) и журналы (var/log/).
vendor/
Здесь находятся сторонние (то есть «поставленные») библиотеки! Они загружаются через менеджер пакетов Composer.
public/
Это корневой каталог вашего проекта: здесь вы размещаете все общедоступные файлы.
#Установка Symfony/flex
composer require symfony/flex
Маршруты
#Параметр condition позволяет выполнять маршрут только в том случае, если он соответствует определенным условиям, например: condition: "params['id'] < 1000"
#Отладочные маршруты:
php bin/console debug:router
php bin/console debug:router --show-aliases
php bin/console debug:router --method=GET
#Информация об определенном маршруте
php bin/console debug:router app_lucky_number
#router:match и показывает, какой маршрут соответствует заданному URL.
php bin/console router:match /lucky/number/8
#В маршрутах Symfony переменные части заключаются в { }. Например, маршрут для отображения #содержимого записи в блоге определяется как /blog/{slug}
#[Route('/blog/{slug}', name: 'blog_show')]
public function show(string $slug): Response
#В маршрутах можно указать любое количество параметров, но каждый из них можно использовать только один раз в каждом маршруте например,
/blog/posts-about-{category}/page/{pageNumber}.
Атрибут requirements в атрибутах Symfony определяет регулярные PHP-выражения, которым должны соответствовать параметры маршрута, чтобы совпадал весь маршрут. Это позволяет:
Ограничить значения параметров (например, требовать, чтобы параметр был числом, датой или UUID)
Перечисление Requirement содержит набор часто используемых констант регулярных выражений, таких как цифры, даты и UUID, которые можно использовать в качестве требований к параметрам маршрута.
Параметры также поддерживают свойства PCRE Unicode, которые представляют собой escape-последовательности, соответствующие общим типам символов. Например, \p{Lu} соответствует любому заглавному символу в любом языке, \p{Greek} соответствует любым греческим буквам и т. д.
При желании требования можно указать для каждого параметра с помощью синтаксиса {parameter_name
Специальные параметры
Помимо ваших собственных параметров, маршруты могут включать в себя любой из следующих специальных параметров, созданных Symfony:
_controller - Этот параметр используется для определения того, какой контроллер и какое действие будут выполнены при совпадении маршрута.
_format - Соответствующее значение используется для установки «формата запроса» объекта Request . Это используется, например, для установки Content-Type ответа (например, формат json преобразуется в Content-Type из application/json).
_fragment - Используется для установки идентификатора фрагмента — необязательной последней части URL, которая начинается с символа # и используется для идентификации части документа.
_locale - Используется для установки языка в запросе.
#[Route(
path: '/articles/{_locale}/search.{_format}',
locale: 'en',
format: 'html',
requirements: [
'_locale' => 'en|fr',
'_format' => 'html|xml',
],
)]
public function search(): Response
Необязательные параметры
В примере ниже, когда пользователь заходит на /blog, маршрут blog_list будет соответствовать запросу, а $page по умолчанию будет иметь значение 1.
#[Route('/blog/{page}', name: 'blog_list', requirements: ['page' => '\d+'])]
public function list(int $page = 1): Response
Может быть несколько необязательных параметров (например, /blog/{slug}/{page}), но все, что следует за необязательным параметром, должно быть необязательным. Например, /{page}/blog — это допустимый путь, но page всегда будет обязательным (то есть /blog не будет соответствовать этому маршруту).
Чтобы в сгенерированном URL всегда указывалось какое-то значение по умолчанию (например, чтобы вместо /blog/1 в предыдущем примере генерировалось /blog), добавьте символ ! перед именем параметра: /blog/{!page}
Как и в случае с требованиями, значения по умолчанию можно указать для каждого параметра с помощью синтаксиса {parameter_name?default_value}
#[Route('/blog/{page<\d+>?1}', name: 'blog_list')]
Чтобы присвоить null значение по умолчанию любому параметру, не добавляйте ничего после символа ? (например, /blog/{page?}). Если вы это сделаете, не забудьте обновить типы соответствующих аргументов контроллера, чтобы можно было передавать значения null (например, замените int $page на ?int $page).
Параметр приоритета
Symfony обрабатывает маршруты в том порядке, в котором они определены.
В YAML и XML можно перемещать определения маршрутов вверх или вниз в файле конфигурации, чтобы управлять их приоритетом.
В маршрутах, определённых как атрибуты, можно использовать необязательный priority параметр
#[Route('/blog/list', name: 'blog_list', priority: 2)]
Получение услуг
Symfony поставляется в комплекте с множеством полезных классов и функций, называемых сервисами. Они используются для рендеринга шаблонов, отправки электронных писем, запросов к базе данных и любой другой «работы», которую вы только можете себе представить.
Если вам нужен сервис в контроллере, укажите тип аргумента с именем его класса (или интерфейса), и Symfony автоматически внедрит его. Для этого ваш контроллер должен быть зарегистрирован как сервис
use Psr\Log\LoggerInterface;
use Symfony\Component\HttpFoundation\Response;
// ...
#[Route('/lucky/number/{max}')]
public function number(int $max, LoggerInterface $logger): Response
{
$logger->info('We are logging!');
// ...
}
Чтобы увидеть список всех сервисов, используйте команду debug:autowiring в консоли:
php83 bin/console debug:autowiring
Преобразование параметров
Преобразование параметров - преобразование значения, хранящегося в каком-либо параметре (например, целого числа, выступающего в роли идентификатора пользователя), в другое значение (например, в объект, представляющий пользователя).
Сохраните предыдущую конфигурацию маршрута, но измените аргументы действия контроллера. Вместо string $slug добавьте BlogPost $post
use App\Entity\BlogPost;
...
#[Route('/blog/{slug:post}', name: 'blog_show')]
public function show(BlogPost $post): Response
Если в аргументах вашего контроллера есть подсказки по типам для объектов (BlogPost в данном случае), «преобразователь параметров» отправляет запрос в базу данных, чтобы найти объект по параметрам запроса (slug в данном случае). Если объект не найден, Symfony автоматически генерирует ответ 404.
Синтаксис {slug:post} сопоставляет параметр маршрута с именем slug с аргументом контроллера с именем $post. Он также указывает «преобразователю параметров» искать соответствующий объект BlogPost в базе данных по идентификатору.
Ознакомьтесь с документацией по преобразованию параметров Doctrine, чтобы узнать, как настроить запросы к базе данных, используемые для получения объекта из параметра маршрута:
https://symfony.com/doc/current/doctrine.html#doctrine-entity-value-resolver
Дополнительные Параметры
В параметре defaults маршрута можно указать параметры, не включенные в конфигурацию маршрута. Это полезно для передачи дополнительных аргументов контроллерам маршрутов.
#[Route('/blog/{page}', name: 'blog_index', defaults: ['page' => 1, 'title' => 'Hello world!'])]
public function index(int $page, string $title): Response
Сглаживание маршрута
Псевдоним маршрута позволяет использовать несколько имён для одного и того же маршрута и может применяться для обеспечения обратной совместимости с маршрутами, которые были переименованы
Допустим есть маршрут:
#[Route('/product/{id}', name: 'product_show')]
public function show(): Response
Теперь предположим, что вы хотите создать новый маршрут под названием product_details , который будет работать точно так же, как product_show
Вместо того чтобы дублировать исходный маршрут, вы можете создать для него псевдоним.
#[Route('/product/{id}', name: 'product_show', alias: ['product_details'])]
public function show(): Response
В этом примере в приложении можно использовать как product_show, так и product_details маршруты, и они будут давать одинаковый результат.
Это невозможно сделать с помощью атрибутов PHP
Контроллер
Контроллер — это созданная вами PHP-функция, которая считывает информацию из объекта Request и создаёт и возвращает объект Response
Ответом может быть HTML-страница, JSON, XML, загрузка файла, перенаправление, ошибка 404 или что-то ещё. Контроллер выполняет любую произвольную логику, необходимую вашему приложению для отображения содержимого страницы
Обычно контроллером называют метод внутри класса контроллера
Примеры методов с возвратом значений:
namespace App\Controller;
use Symfony\Component\HttpFoundation\Response;
use Symfony\Component\Routing\Attribute\Route;
class LuckyController
{
#[Route('/lucky/number/{max}', name: 'app_lucky_number')]
public function number(int $max): Response
{
$number = random_int(0, $max);
return new Response(
'Lucky number: '.$number.''
);
}
}
namespace App\Controller; - Symfony использует функцию пространства имён PHP для присвоения пространства имён всему классу контроллера.
use Symfony\Component\HttpFoundation\Response; - Symfony снова использует возможности пространства имён PHP: ключевое слово use импортирует класс Response, который должен возвращать контроллер.
Чтобы просмотреть результат работы этого контроллера, вам нужно сопоставить с ним URL-адрес с помощью маршрута. Это было сделано выше с помощью #[Route('/lucky/number/{max}')] атрибута route.
Для упрощения разработки в Symfony предусмотрен дополнительный базовый класс контроллера под названием AbstractController. Его можно расширить, чтобы получить доступ к вспомогательным методам.
Для его использования необходимо добавить следующие строки:
use Symfony\Bundle\FrameworkBundle\Controller\AbstractController;
class LuckyController extends AbstractController
namespace App\Controller;
use Symfony\Bundle\FrameworkBundle\Controller\AbstractController;
use Symfony\Component\HttpFoundation\Response;
class UserController extends AbstractController
{
// ...
public function notifications(): Response
{
// get the user information and notifications somehow
$userFirstName = '...';
$userNotifications = ['...', '...'];
// the template path is the relative file path from `templates/`
return $this->render('user/notifications.html.twig', [
// this array defines the variables passed to the template,
// where the key is the variable name and the value is the variable value
// (Twig recommends using snake_case variable names: 'foo_bar' instead of 'fooBar')
'user_first_name' => $userFirstName,
'notifications' => $userNotifications,
]);
}
}
Генерация URL-адресов
Метод generateUrl() — это вспомогательный метод, который генерирует URL для заданного маршрута.
$url = $this->generateUrl('app_lucky_number', ['max' => 10]);
Перенаправление
Если вы хотите перенаправить пользователя на другую страницу, используйте методы redirectToRoute() и redirect()
return $this->redirectToRoute('homepage');
Шаблоны рендеринга
Если вы обслуживаете HTML-страницы, вам нужно отобразить шаблон. Метод render() отображает шаблон и помещает его содержимое в объект Response
return $this->render('lucky/number.html.twig', ['number' => $number]);
Генерация Контроллеров
Чтобы сэкономить время, вы можете установить Symfony Maker и попросить Symfony сгенерировать новый класс контроллера:
php bin/console make:controller BrandNewController
created: src/Controller/BrandNewController.php
created: templates/brandnew/index.html.twig
Если вы хотите сгенерировать весь CRUD из Doctrine entity, используйте:
php bin/console make:crud Product
Обработка ошибок и страниц с кодом 404
Если данные не найдены, следует вернуть ответ с кодом 404. Для этого нужно вызвать исключение особого типа:
use Symfony\Component\HttpKernel\Exception\NotFoundHttpException;
...
$product = ...;
if (!$product) {
throw $this->createNotFoundException('The product does not exist');
...
Метод createNotFoundException() — это просто сокращённый способ создания специального NotFoundHttpException объекта, который в конечном счёте вызывает HTTP-ответ 404 в Symfony.
Если вы создадите исключение, которое расширяет HttpException или является его экземпляром, Symfony будет использовать соответствующий код состояния HTTP. В противном случае ответ будет содержать код состояния HTTP 500:
throw new \Exception('Something went wrong!');
Чтобы настроить страницу с ошибкой, которая отображается для пользователя, ознакомьтесь со статьёй:
https://symfony.com/doc/current/controller/error_pages.html
Объект Request в качестве аргумента контроллера
Что делать, если вам нужно прочитать параметры запроса, получить заголовок запроса или доступ к загруженному файлу? Эта информация хранится в объекте Request Symfony. Чтобы получить к нему доступ в вашем контроллере, добавьте его в качестве аргумента и укажите его тип с помощью класса Request:
use Symfony\Component\HttpFoundation\Request;
use Symfony\Component\HttpFoundation\Response;
// ...
public function index(Request $request): Response
{
$page = $request->query->get('page', 1);
// ...
}
Автоматическое Сопоставление запроса
Можно автоматически сопоставить полезную нагрузку запроса и/или параметры запроса с аргументами действия вашего контроллера с помощью атрибутов.
Допустим, пользователь отправляет вам запрос со следующей строкой запроса: https://example.com/dashboard?firstName=John&lastName=Smith&age=27. Благодаря атрибуту MapQueryParameter аргументы действия вашего контроллера могут быть заполнены автоматически:
use Symfony\Component\HttpKernel\Attribute\MapQueryParameter;
...
public function dashboard(
#[MapQueryParameter] string $firstName,
#[MapQueryParameter] string $lastName,
#[MapQueryParameter] int $age,
): Response
....
[MapQueryParameter] может принимать необязательный аргумент filter
#[MapQueryParameter(filter: \FILTER_VALIDATE_REGEXP, options: ['regexp' => '/^\w+$/'])] string $firstName,
#[MapQueryParameter] string $lastName,
#[MapQueryParameter(filter: \FILTER_VALIDATE_INT)] int $age,
Другой вариант — преобразовать всю строку запроса в объект, который будет содержать доступные параметры запроса.
Шаблоны
Создание и использование шаблонов
Шаблон — это лучший способ организации и отображения HTML-кода внутри вашего приложения, независимо от того, нужно ли вам отобразить HTML-код из контроллера или сгенерировать содержимое электронного письма. Шаблоны в Symfony создаются с помощью Twig — гибкого, быстрого и безопасного шаблонизатора.
#Установка
composer require symfony/twig-bundle
Синтаксис Twig основан на этих трёх конструкциях:
{{ ... }} - Используется для отображения содержимого переменной или результата вычисления выражения.
{% ... %} - Используется для выполнения некоторых логических операций, таких как условие или цикл.
{# ... #} - Используется для добавления комментариев к шаблону (в отличие от HTML-комментариев, эти комментарии не включаются в отображаемую страницу).
Фильтры изменяют содержимое перед отображением, как и upper-фильтр, который преобразует содержимое в верхний регистр:
{{ title|upper }}
В Twig есть длинный список тегов, фильтров и функций, которые доступны по умолчанию. В приложениях Symfony вы также можете использовать эти фильтры и функции Twig, определённые в Symfony и создавать собственные фильтры и функции Twig.
https://twig.symfony.com/doc/3.x/tags/index.html
https://twig.symfony.com/doc/3.x/filters/index.html
https://twig.symfony.com/doc/3.x/functions/index.html
https://symfony.com/doc/current/reference/twig_reference.html
https://symfony.com/doc/current/templates.html#templates-twig-extension
В Twig есть несколько параметров конфигурации, с помощью которых можно задать такие параметры, как формат отображения чисел и дат, кэширование шаблонов и т. д
https://symfony.com/doc/current/reference/configuration/twig.html
Каталог шаблонов по умолчанию настраивается с помощью параметра twig.default_path. Вы можете добавить дополнительные каталоги шаблонов
Переменные шаблона
Обычно шаблоны нужны для того, чтобы выводить значения, хранящиеся в шаблонах и передаваемые из контроллера или сервиса. В переменных обычно хранятся объекты и массивы, а не строки, числа и логические значения.
{{ user.name }} added this comment on {{ comment.publishedAt|date }}
Обозначение user.name означает, что вы хотите отобразить некоторую информацию (name), хранящуюся в переменной (user). Является ли user массивом или объектом? Является ли name свойством или методом? В Twig это не имеет значения.
При использовании foo.bar Twig пытается получить значение переменной в следующем порядке:
$foo['bar'] (массив и элемент);
$foo->bar (объект и общедоступное свойство);
$foo->bar() (объект и общедоступный метод);
$foo->getBar() (объект и метод получения данных);
$foo->isBar() (объект и метод isser);
$foo->hasBar() (объект и метод хассера);
Если ничего из вышеперечисленного не существует, используйте null (или вызовите исключение Twig\Error\RuntimeError , если включена опция strict_variables).
Ссылки на Страницы
Вместо того чтобы вручную вводить URL-адреса ссылок, используйте функцию path() для создания URL-адресов на основе конфигурации маршрутизации.
Ссылки на CSS, JavaScript и изображения
Если шаблону нужна ссылка на статический ресурс (например, изображение), Symfony предоставляет функцию asset() Twig для создания такого URL. Сначала установите пакет asset:
Использование функции asset() рекомендуется по следующим причинам:
Управление версиями ресурсов: asset() добавляет хэш версии к URL-адресам ресурсов для очистки кэша
Переносимость приложения: независимо от того, размещено ли ваше приложение в корневом каталоге (например, https://example.com) или в подкаталоге (например, https://example.com/my_app), asset() автоматически генерирует правильный путь (например, /images/logo.png вместо /my_app/images/logo.png) на основе базового URL вашего приложения.
{# the image lives at "public/images/logo.png" #}
<img src="{{ asset('images/logo.png') }}" alt="Symfony!">
{# the CSS file lives at "public/css/blog.css" #}
<link href="{{ asset('css/blog.css') }}" rel="stylesheet">
{# the JS file lives at "public/bundles/acme/js/loader.js" #}
<script src="{{ asset('bundles/acme/js/loader.js') }}">
Если вам нужны абсолютные URL-адреса для ресурсов, используйте функцию absolute_url()
<img src="{{ absolute_url(asset('images/logo.png')) }}" alt="Symfony!">
<link rel="shortcut icon" href="{{ absolute_url('favicon.png') }}">
Глобальные переменные
Twig позволяет автоматически подставлять одну или несколько переменных во все шаблоны. Эти глобальные переменные определяются с помощью опции twig.globals в основном файле конфигурации Twig:
# config/packages/twig.yaml
twig:
# ...
globals:
ga_tracking: 'UA-xxxxx-x'
Теперь переменная ga_tracking доступна во всех шаблонах Twig, поэтому вы можете использовать её без необходимости передавать её явно из контроллера или сервиса, который отображает шаблон.
The Google tracking code is: {{ ga_tracking }}
Помимо статических значений, глобальные переменные Twig могут ссылаться на сервисы из контейнера сервисов
twig:
# ...
globals:
# the value is the service's id
uuid: '@App\Generator\UuidGenerator'
Twig Components
Компоненты Twig — это альтернативный способ рендеринга шаблонов, при котором каждый шаблон привязывается к «классу компонента» Это упрощает рендеринг и повторное использование небольших «блоков» шаблонов, таких как оповещение, разметка для модального окна или боковая панель категорий.
https://symfony.com/bundles/ux-twig-component/current/index.html
У компонентов Twig есть ещё одна суперспособность: они могут быть «живыми», то есть автоматически обновляться (через Ajax) при взаимодействии с ними пользователя. Например, когда пользователь вводит текст в поле, компонент Twig повторно отображается через Ajax, чтобы показать список результатов!
https://symfony.com/bundles/ux-live-component/current/index.html
Шаблоны рендеринга
Если ваш контроллер наследуется от AbstractController, используйте вспомогательную функцию render():
namespace App\Controller;
use Symfony\Bundle\FrameworkBundle\Controller\AbstractController;
use Symfony\Component\HttpFoundation\Response;
class ProductController extends AbstractController
{
public function index(): Response
{
// ...
// the `render()` method returns a `Response` object with the
// contents created by the template
return $this->render('product/index.html.twig', [
'category' => '...',
'promotions' => ['...', '...'],
]);
Если ваш контроллер не наследуется от AbstractController, вам нужно будет получить сервисы в вашем контроллере и использовать render() метод сервиса twig
https://symfony.com/doc/current/controller.html#controller-accessing-services
Другой вариант — использовать атрибут #[Template] в методе контроллера для определения отображаемого шаблона:
use Symfony\Bridge\Twig\Attribute\Template;
...
#[Template('product/index.html.twig')]
public function index(): array
...
return [
'category' => '...',
'promotions' => ['...', '...'],
];
базовый класс AbstractController также предоставляет методы renderBlock() и renderBlockView() :
public function price(): Response
{
// ...
// the `renderBlock()` method returns a `Response` object with the
// block contents
return $this->renderBlock('product/index.html.twig', 'price_block', [
// ...
]);
// the `renderBlockView()` method only returns the contents created by the
// template block, so you can use those contents later in a `Response` object
$contents = $this->renderBlockView('product/index.html.twig', 'price_block', [
// ...
]);
return new Response($contents);
}
Повторное использование содержимого шаблона
Функция include() в Twig принимает в качестве аргумента путь к включаемому шаблону. Включаемый шаблон имеет доступ ко всем переменным включающего его шаблона (для управления этим используйте опцию with_context
{{ include('blog/_user_profile.html.twig') }}
Вы также можете передавать переменные во включенный шаблон. Это полезно, например, для переименования переменных. Представьте, что ваш шаблон хранит информацию о пользователе в переменной blog_post.author вместо переменной user, которую ожидает фрагмент шаблона. Чтобы переименовать переменную, используйте следующий код:
{{ include('blog/_user_profile.html.twig', {user: blog_post.author}) }}
Встраивание контроллеров
Встраивание контроллеров - встраивание результата выполнения какого-либо контроллера с помощью функций render() и controller() в Twig
Например создадим контроллер, который отображает определённое количество последних статей:
public function recentArticles(int $max = 3): Response
{
// get the recent articles somehow (e.g. making a database query)
$articles = ['...', '...', '...'];
return $this->render('blog/_recent_articles.html.twig', [
'articles' => $articles
]);
}
Затем необходимо создать фрагмент шаблона
{# templates/blog/_recent_articles.html.twig #}
{% for article in articles %}
{{ article.title }}
{% endfor %}
Теперь можно обратиться к этому контроллеру из любого шаблона, чтобы получить его результат:
При использовании функции controller() доступ к контроллерам осуществляется не по обычному маршруту Symfony, а по специальному URL-адресу, который используется исключительно для обслуживания этих фрагментов шаблона. Настройте этот специальный URL-адрес в параметре fragments:
# config/packages/framework.yaml
framework:
# ...
fragments: { path: /_fragment }
Наследование шаблонов и макеты
По мере роста вашего приложения вы будете находить всё больше повторяющихся элементов на разных страницах, таких как верхние и нижние колонтитулы, боковые панели и т. д. Включение шаблонов и встраивание контроллеров могут помочь, но если страницы имеют общую структуру, лучше использовать наследование.
Концепция наследования шаблонов Twig аналогична наследованию классов в PHP. Вы определяете родительский шаблон, от которого могут наследоваться другие шаблоны, а дочерние шаблоны могут переопределять части родительского шаблона.
templates/base.html.twigопределяет общие элементы для всех шаблонов приложений, такие как <head>, <header>, <footer> и т. д.;
templates/layout.html.twig, наследуется от base.html.twig и определяет структуру контента, используемую на всех или большинстве страниц, например макет с двумя столбцами контента и боковой панелью. Некоторые разделы приложения могут иметь собственные макеты (например, templates/blog/layout.html.twig);
templates/*.html.twig, страницы приложения, которые расширяют возможности основного шаблона layout.html.twig или любого другого макета раздела.
{# templates/blog/layout.html.twig #}
{% extends 'base.html.twig' %}
{% block content %}
Blog
{% block page_contents %}{% endblock %}
{% endblock %}
Ознакомьтесь с документацией по наследованию шаблонов Twig
https://twig.symfony.com/doc/3.x/tags/extends.html
Настройка подключения к базе данных
#Установка доктрины
composer require symfony/orm-pack
composer require --dev symfony/maker-bundle
#Редактируем файл .env
DATABASE_URL="postgresql://db_user:db_password@127.0.0.1:5432/db_name?serverVersion=12.19 (Debian 12.19-1.pgdg120+1)&charset=utf8"
#Выполняем пробный запрос
php bin/console dbal:run-sql 'SELECT * FROM users'
Конфигурация
Приложения Symfony настраиваются с помощью файлов, хранящихся в каталоге config/, который по умолчанию имеет следующую структуру:
your-project/
├─ config/
│ ├─ packages/
│ ├─ bundles.php
│ ├─ routes.yaml
│ └─ services.yaml
Файл routes.yaml определяет конфигурацию маршрутизации;
Файл services.yaml настраивает службы контейнера служб;
Файл bundles.php включает и отключает пакеты в вашем приложении.
В каталоге config/packages/ хранится конфигурация каждого пакета, установленного в вашем приложении.
Чтобы узнать обо всех доступных параметрах конфигурации, ознакомьтесь со Справочником по конфигурации Symfony:
https://symfony.com/doc/current/reference/index.html
Или выполните команду config:dump-reference
Импорт файлов конфигурации
Symfony загружает файлы конфигурации с помощью компонента Config, который предоставляет расширенные возможности, такие как импорт других файлов конфигурации, даже если они имеют другой формат.
imports:
- { resource: 'legacy_config.php' }
# glob expressions are also supported to load multiple files
- { resource: '/etc/myapp/*.yaml' }
# ignore_errors: not_found silently discards errors if the loaded file doesn't exist
- { resource: 'my_config_file.xml', ignore_errors: not_found }
# ignore_errors: true silently discards all errors (including invalid code and not found)
- { resource: 'my_other_config_file.xml', ignore_errors: true }
Сборка, управление версиями и другие продвинутые функции CSS, JavaScript и обработки изображений
Чтобы узнать, как создавать и обновлять версии ресурсов JavaScript и CSS современным способом, прочтите о Symfony AssetMapper.
Глобальная переменная приложения
Symfony создаёт объект контекста, который автоматически внедряется в каждый шаблон Twig в виде переменной app. Он предоставляет доступ к некоторой информации о приложении:
Username: {{ app.user.username ?? 'Anonymous user' }}
{% if app.debug %}
Request method: {{ app.request.method }}
Application Environment: {{ app.environment }}
{% endif %}
Переменная app (которая является экземпляром AppVariable) предоставляет доступ к следующим переменным:
app.user - Текущий объект пользователя или null если пользователь не прошёл аутентификацию.
app.request - Объект Request, в котором хранятся текущие данные запроса (в зависимости от вашего приложения это может быть подзапрос или обычный запрос).
app.session - Объект Session, представляющий текущую сессию пользователя или null, если таковой нет.
app.flashes - Массив всех всплывающих сообщений, сохранённых в сеансе. Вы также можете получить только сообщения определённого типа (например, app.flashes('notice')).
app.environment - Название текущей среды конфигурации (dev, prod, и т. д.).
app.debug - True, если в режиме отладки. False в противном случае.
app.token - Объект TokenInterface, представляющий токен безопасности.
app.current_route - Название маршрута, связанного с текущим запросом, или null если запрос отсутствует (эквивалентно app.request.attributes.get('_route'))
app.current_route_parameters - Массив с параметрами, переданными в маршрут текущего запроса, или пустой массив, если запрос отсутствует (эквивалентно app.request.attributes.get('_route_params'))
app.locale - Локаль, используемый в текущем переключателе локалей контексте.
app.enabled_locales - Локали, поддерживаемые приложением.
Помимо глобальной переменной app, добавляемой Symfony, вы также можете автоматически добавлять переменные во все шаблоны Twig
Параметры конфигурации
По соглашению, параметры определяются под ключом parameters в файле config/services.yaml
# config/services.yaml
parameters:
# the parameter name is an arbitrary string (the 'app.' prefix is recommended
# to better differentiate your parameters from Symfony parameters).
app.admin_email: 'something@example.com'
# boolean parameters
app.enable_v2_protocol: true
# array/collection parameters
app.supported_locales: ['en', 'es', 'fr']
# binary content parameters (encode the contents with base64_encode())
app.some_parameter: !!binary VGhpcyBpcyBhIEJlbGwgY2hhciAH
# PHP constants as parameter values
app.some_constant: !php/const GLOBAL_CONSTANT
app.another_constant: !php/const App\Entity\BlogPost::MAX_ITEMS
# Enum case as parameter values
app.some_enum: !php/enum App\Enum\PostState::Published
Конфигурационные среды
Типичное приложение на Symfony состоит из трёх сред:
dev для местного развития
prod для производственных серверов
test для автоматизированных тестов
При запуске приложения Symfony загружает файлы конфигурации в следующем порядке (последние файлы могут переопределять значения, заданные в предыдущих файлах):
Файлы в config/packages/*.
файлы в config/packages/
Вы также можете задать параметры для различных сред в одном файле конфигурации, используя специальное ключевое слово when:
# config/packages/webpack_encore.yaml
webpack_encore:
# ...
output_path: '%kernel.project_dir%/public/build'
strict_mode: true
cache: false
# cache is enabled only in the "prod" environment
when@prod:
webpack_encore:
cache: true
# disable strict mode only in the "test" environment
when@test:
webpack_encore:
strict_mode: false
# YAML syntax allows to reuse contents using "anchors" (&some_name) and "aliases" (*some_name).
# In this example, 'test' configuration uses the exact same configuration as in 'prod'
when@prod: &webpack_prod
webpack_encore:
# ...
when@test: *webpack_prod
Чтобы узнать всё о порядке загрузки файлов конфигурации, изучите метод configureContainer()класса Kernel.
В приложениях Symfony есть файл .env в корневом каталоге проекта. Этот файл используется для определения значений переменных среды.
Создание новой среды
Трёх сред, предоставляемых Symfony по умолчанию, достаточно для большинства проектов, но вы можете создать и свои собственные.
Переменные окружения
Чтобы задать значение переменной окружения, можно воспользоваться несколькими способами:
Добавьте значение в файл .env;
Зашифруйте значение как секретное;
Установите значение в качестве реальной переменной среды в вашей оболочке или на вашем веб-сервере.
Файл .env считывается и анализируется при каждом запросе, а его переменные окружения добавляются к переменным $_ENV и $_SERVER в PHP. Любые существующие переменные окружения никогда не перезаписываются значениями, указанными в .env, поэтому вы можете использовать и то, и другое.
Поскольку файл .env считывается и анализируется при каждом запросе, вам не нужно очищать кэш Symfony или перезапускать PHP-контейнер, если вы используете Docker.
Если вам нужно переопределить значение переменной среды (например, установить другое значение на локальном компьютере), вы можете сделать это в файле .env.local
Доступ к переменным окружения также можно получить с помощью суперглобальных переменных PHP $_ENV и $_SERVER (оба варианта эквивалентны)
Реальные переменные среды всегда имеют приоритет над переменными среды, созданными любым из .env файлов
$databaseUrl = $_ENV['DATABASE_URL']; // mysql://db_user:db_password@127.0.0.1:3306/db_name
$env = $_SERVER['APP_ENV']; // prod
#Используйте переменные среды в значениях, добавляя к переменным префикс $:
DB_USER=root
DB_PASS=${DB_USER}pass # include the user as a password prefix
#Укажите значение по умолчанию на случай, если переменная среды не задана:
DB_USER=
DB_PASS=${DB_USER:-root}pass # results in DB_PASS=rootpass
#Вставляйте команды через $() (не поддерживается в Windows):
START_TIME=$(date)
Если вам нужно переопределить переменную среды, заданную системой, используйте параметр overrideExistingVars, заданный методами loadEnv(), bootEnv() и populate()
Это переопределит переменные среды, заданные системой, но не переопределит переменные среды, заданные в .env файлах.
use Symfony\Component\Dotenv\Dotenv;
$dotenv = new Dotenv();
$dotenv->loadEnv(__DIR__.'/.env', overrideExistingVars: true);
// ...
Если вам нужно узнать путь к файлу .env, который использует Symfony, вы можете прочитать переменную среды SYMFONY_DOTENV_PATH в своём приложении.
Вместо определения реальной переменной окружения или добавления ее в .env файл, если значение переменной конфиденциально (например, ключ API или пароль базы данных), вы можете зашифровать значение с помощью системы управления секретами.
Используйте команду debug:dotenv, чтобы понять, как Symfony анализирует различные файлы .env для установки значения каждой переменной среды:
Кроме того, независимо от того, как вы задаёте переменные среды, вы можете увидеть все переменные среды с их значениями, на которые ссылается конфигурация контейнера Symfony. Вы также можете увидеть количество упоминаний каждой переменной среды в контейнере:
php bin/console debug:container --env-vars
Доступ к Параметрам Конфигурации
Чтобы просмотреть все параметры, существующие в вашем приложении, выполните следующую команду:
php bin/console debug:container --parameters
В контроллерах, производных от AbstractController, используйте вспомогательную функцию getParameter():
// src/Controller/UserController.php
namespace App\Controller;
use Symfony\Bundle\FrameworkBundle\Controller\AbstractController;
use Symfony\Component\HttpFoundation\Response;
class UserController extends AbstractController
{
// ...
public function index(): Response
{
$projectDir = $this->getParameter('kernel.project_dir');
$adminEmail = $this->getParameter('app.admin_email');
// ...
}
}
Безопасность
Пакет SecurityBundle предоставляет все функции аутентификации и авторизации
composer require symfony/security-bundle
Создание сущности User
Самый простой способ создать пользовательский класс — использовать команду make:user из MakerBundle:
php bin/console make:user
...
created: src/Entity/User.php
created: src/Repository/UserRepository.php
updated: src/Entity/User.php
updated: config/packages/security.yaml
Если ваш пользователь является объектом Doctrine, как в примере выше, не забудьте создать таблицы с помощью создания и запуска миграции:
https://symfony.com/doc/current/doctrine.html#doctrine-creating-the-database-tables-schema
php bin/console make:migration
php bin/console doctrine:migrations:migrate
Создать форму регистрации
Команда make:registration-form maker поможет вам настроить контроллер регистрации
Команда composer require symfonycasts/verify-email-bundle, дабавит такие функции, как проверка адреса электронной почты
composer require symfonycasts/verify-email-bundle
php bin/console make:registration-form
....
updated: src/Entity/User.php
updated: src/Entity/User.php
created: src/Security/EmailVerifier.php
created: templates/registration/confirmation_email.html.twig
created: src/Form/RegistrationFormType.php
created: src/Controller/RegistrationController.php
created: templates/registration/register.html.twig
php bin/console make:migration
php bin/console doctrine:migrations:migrate
Форма Входа в систему
Чтобы создать всё необходимое для добавления формы входа в ваше приложение, выполните следующую команду:
php bin/console make:security:form-login
...
created: src/Controller/SecurityController.php
created: templates/security/login.html.twig
updated: config/packages/security.yaml
...
php bin/console make:migration
php bin/console doctrine:migrations:migrate
Защита маршрута
Возможны два варианта защиты маршрута:
Через атрибуты контроллера
Через security.yaml
use Symfony\Component\Security\Http\Attribute\IsGranted;
...
#[IsGranted('ROLE_USER')]
#[Route('/actions/content', name: 'app_actions_content')]
public function AddContent()...
........
Источники:
https://max-gabov.ru/urok-8-autentifikaciya-v-symfony






