Назначение и установка Symfony Framework

Использование фреймворков позволяет структурировать разработку, повторно использовать общие модули, облегчает долгосрочное обслуживание и масштабируемость в соответствии со стандартными правилами разработки. По сравнению с CMS, фреймворки обеспечивают гибкость и могут быть использованы для разработки приложений, которые наиболее точно соответствуют заявленным требованиям, но в тоже время требуют определённые технические знания, связанные с разработкой, интеграцией и техническим обслуживанием [19].

По сравнению с самописными приложениями, использование фреймворков гарантирует соответствие кода современным стандартам, структурирование, поддержку и масштабируемость. А также сокращает время разработки, позволяет повторно использовать модули [20].

Symfony Framework – свободный PHP-фреймворк, разработанный компанией Sensio Labs в соответствии с паттерном MVC и предназначенный для создания сайтов и веб-приложений. Он простроен на основе компонентов Symfony, каждый из которых может быть использован отдельно от самого фреймворка. Первый релиз состоялся 22 октября 2005 года. Последней версией является 3.3.2 (6 июня 2017 года), требует PHP 5.5.9 и выше, поддерживает большое количество баз данных (PostgrerSQL, MySQL, SQLite) благодаря ORM-инструменту Doctrine. Одна из самых популярных CMS – Drupal 8 основа на Symfony Framework [21].

Symfony предоставляет специальное приложение под названием Symfony Installer для упрощения создания приложений Symfony. Этот установщик представляет собой исполняемый файл, совместимый с PHP 5.4, который должен быть установлен в системе только один раз:

#Linux и MacOS

sudo mkdir -p /usr/local/bin

sudo curl -LsS https://symfony.com/installer -o /usr/local/bin/symfony

sudo chmod a+x /usr/local/bin/symfony

#Widnows

php -r "readfile('https://symfony.com/installer');" > symfony

Листинг 2. Команды для установки Symfony Installer

После установки Symfony Installer для создания приложения Symfony необходимо ввести команду «symfony new project_name».

Эта команда создает новый каталог, project_name/ который содержит пустой проект, основанный на последней версии стабильной версии Symfony. Кроме того, установщик проверяет, соответствует ли система техническим требованиям для выполнения приложений Symfony. Если нет, отобразится список изменений, необходимых для удовлетворения этих требований.

Также имеется возможность создавать приложения Symfony с помощью Composer, менеджера зависимостей, используемого современными PHP-приложениями. Для этого используется команда «composer create-project symfony/framework-standard-edition project_name». Для обновления компонентов Symfony используется команда «php bin/console server:run».

Symfony использует внутренний веб-сервер PHP (доступный с PHP 5.4) для запуска приложений при их разработке. Запуск приложения Symfony осуществляется командой «php bin/console server:run». После этого необходимо перейти в браузере по адресу http://localhost:8000/. Если установка прошла успешно, и система удовлетворяет требованием отобразится страница приветствия (рис. 5).

Назначение и установка Symfony Framework - student2.ru

Рис. 5. Страница приветствия Symfony 2.8.0

Структура Symfony Framework

В последующих подпунктах будет произведён анализ технологий Symfony Framework на основе официальной документации [15].

Конфигурация

Каждое приложение Symfony состоит из набора бандлов (пакетов), которые добавляют инструменты (севрисы) в проект. Каждый бандл может быть настроен через файлы конфигурации, которые по умолчанию расположены в каталоге app/config (см. листинг 3).

imports:

- { resource: parameters.yml }

- { resource: security.yml }

- { resource: services.yml }

framework:

secret: '%secret%'

router: { resource: '%kernel.project_dir%/app/config/routing.yml' }

# ...

# Twig Configuration

twig:

debug: '%kernel.debug%'

strict_variables: '%kernel.debug%'

Листинг 3. Главный файл конфигурации config.yml

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

Для того, чтобы использовать какие параметры можно настроить необходимо использовать справочный раздел, либо команду «php bin/console config:dump-reference название_библиотеки». Для импорта настроек используется специальный ключ imports, который работает аналогичного include в PHP. Другой специальный ключ называется parameters: он используется для определения переменных, на которые можно ссылаться в другом файле конфигурации. Чтобы ссылаться на параметр, необходимо окружить его название двумя знаками процента. Параметры, которые являются уникальными для каждого сервера, например, учетные данные базы данных, должны быть описаны в файле paramentrs.yml, а данный файл исключен из версионного контроля. Но данные параметры могут быть описаны в файле paramentrs.yml.dist в виде фиктивных значений (шаблонов). При разворачивании проекта через composer Symfony предложит ввести фактические значения данных параметров.

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

Бандлы

Бандл похож на плагин в различных ПО. Главное отличие заключается в том, что все бандлы в Symfony, включая базовые компоненты фреймворка, написаны для конкретного пользователя. Бандлы – основа Symfony. Они предоставляют гибкость в использовании предварительно встроенных функций, упакованных в сторонние пакеты или для распространения собственных пакетов. Это позволяет легко выбирать, какие функции включить в приложении, и оптимизировать их с учётом собственных потребностей.

Пакет представляет собой просто структурированный набор файлов в каталоге, реализующем одну функцию. Каждый каталог содержит все, что связано с этой функцией, включая файлы PHP, шаблоны, таблицы стилей, файлы JavaScript, тесты и все остальное. Каждый аспект функции существует в бандле, и каждая функция расположена в бандле.

Бандлы, используемые в приложениях, должны быть включены путем регистрации их в методе registerBundles() класса AppKernel в файле app/AppKernel.php. Таким образом можно контролировать, какие бандлы необходимо использовать в проекте, а какие нет. Для вызова классов используется автозагрузчик, поставляемый вместе с composer.

Для создания нового бандла необходимо создать директорию src/Имя_разработчика/Название_бандлаBundle, а в ней класс с именем Имя_разработчикаНазвание_бандлаBundle и унаследоваться от базового класса Symfony\Component\HttpKernel\Bundle\Bundle. Далее зарегистрировать созданный бандл в классе AppKernel. В качестве альтернативы можно использовать консольную команду php bin/console generate:bundle --namespace=Имя_разработчика/Название_бандлаBundle. Данная команда генерирует базовый контроллер, шаблон и ресурс маршрутизации.

Каждый бандл обладает следующе структурой каталогов:

· Controller/

Содержит контроллеры бандла.

· DependencyInjection/

Содержит определенные классы расширения Dependency Injection, которые могут импортировать конфигурацию сервисов, описывать собственные сервисы и т. д. (этот каталог не обязателен).

· Resources/config/

Конфигурация бандла, включая конфигурацию маршрутизации (например routing.yml).

· Resources/views/

Содержит шаблоны, организованные по имени контроллера (например, Random/index.html.twig).

· Resources/public/

Содержит веб-ресурсы (изображения, таблицы стилей и т. д.), которые будут скопированы или символически связаны в с web/ каталогом проекта с помощью команды assets:install в консоли.

· Tests/

Содержит все тесты для бандла.

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

Установка стороннего бандла происходит в три этапа:

1. Поиск названия бандла на сайте http://packagist.org и установить его через composer, например, «composer require friendsofsymfony/user-bundle». Эта команда установит последнюю версию бандла, добавит ей в файл composer.json и загрузит в каталог vendor/ проекта.

2. Регистрация бандла в классе AppKernel. В зависимости от специфики бандла, можно зарегистрировать его только для определённой среды разработки.

3. Настройка бандла. Для получения списка доступных параметров конфигурации используется команда «php bin/console config:dump-reference НазваниеБандла». После можно переопределить необходимые параметры в файле app/config/config.yml.

Удаление бандла – более сложный процесс по сравнению с его установкой и происходит в четыре этапа:

1. Удалить регистрацию бандла из класса AppKernel.

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

3. Удалить каталог бандла из директории src/, удалить таблицы стилей, скрипты, картинки из директории web/.

4. Если удаляемый бандл связан с другими, необходимо удалить и все связанные бандлы, так как они не смогут функционировать без удалённой зависимости.

Сущности Doctrine

Одной из наиболее распространенных и сложных задач для любого приложения является сохранение и чтение информации в базу данных и из нее. Symfony Framework не интегрирует какой-либо компонент для работы с базами данных, но обеспечивает тесную интеграцию с сторонней библиотекой под названием Doctrine. Единственная цель Doctrine - предоставить мощные инструменты для легкого и гибкого взаимодействия с базами данных. Он сопоставляет объекты с реляционной базой данных (например, MySQL, PostgreSQL или Microsoft SQL). Также имеется возможность сохранения данных в NoSQL базе данных MongoDB с помощью Doctrine ODM library.

Далее в этом подпункте будет приведён пример создания конкретной базы данных под названием test_project и объекта Product.

Информация о подключении к базе данных описывается в файле конфигурации parameters.yml в виде переменных параметров, которые будут использованы в главном файле конфигурации.

# app/config/config.yml

doctrine:

dbal:

driver: pdo_mysql

host: '%database_host%'

dbname: '%database_name%'

user: '%database_user%'

password: '%database_password%'

Листинг 4. Параметры подключения к базе данных

После настроек подключения Doctrine имеет возможность подключиться к базе данных. С помощью команды «php bin/console doctrine:database:create» Doctrine автоматически сгенерирует пустую базу данных. При использовании SQLite в качестве базы данных, необходимо указать путь, в котором должен храниться файл базы данных. Для этого используется параметр doctrine.dbal.path.

Следующим этапом является создание сущности, а именно класса, расположенного в папке Entity внутри каталога бандла. Данный класс может быть сгенерирован автоматически, с помощью команды «php bin/console doctrine:generate:entity». Данная команда задаёт интерактивные вопросы, которые помогают создать разработчику любой объект.

Doctrine позволяет работать с базами данных гораздо более продуктивным способом, чем просто набор строк скалярных данных в массиве. Вместо этого Doctrine позволяет извлекать целые объекты из базы данных и сохранять целые объекты в базе данных. Чтобы Doctrine мог это сделать, необходимо сопоставить таблицы базы данных с определенными классами PHP, а столбцы этих таблиц должны быть сопоставлены определенным свойствам в соответствующих классах PHP.

Назначение и установка Symfony Framework - student2.ru

Рис. 6. Пример сопоставления таблицы БД с PHP-объектом

Эта информация представляется в виде «метаданных», набора правил, который сообщает Doctrine, как именно класс и его свойства должны быть сопоставлены с конкретной таблицей базы данных. Эти метаданные могут быть указаны в нескольких разных форматах, включая YAML, XML или непосредственно внутри класса с помощью DocBlock аннотаций. Разработчик имеет возможность выбрать наиболее удобный способ определения метаданных, но наиболее распространённым вариантом является использование аннотаций. Бандл может принимать только один формат определения метаданных. Например, невозможно сопоставить определения метаданных YAML с аннотированными определениями сущностей PHP. Имя таблицы является необязательным и, если оно опущено, будет определяться автоматически на основе имени класса сущности.

<?
namespace AppBundle\Entity;

use Doctrine\ORM\Mapping as ORM;

/**

* @ORM\Entity

* @ORM\Table(name="product")

*/

Class Product

{

/**

* @ORM\Column(type="integer")

* @ORM\Id

* @ORM\GeneratedValue(strategy="AUTO")

*/

private $id;

/**

* @ORM\Column(type="string", length=100)

*/

private $name;

/**

* @ORM\Column(type="decimal", scale=2)

*/

private $price;

/**

* @ORM\Column(type="text")

*/

private $description;

}

Листинг 5. Пример ORM-сущности Doctrine с описанием в виде аннотаций

После создания сущностей необходимо проверить её описание с помощью команды «php bin/console doctrine:schema:validate».

Не смотря на то, что Doctrine имеет представление о том, как сохранить объект в базе данных, класс приведённый в листинге 5 является бесполезным. Поскольку Product - это обычный PHP-класс со private свойствами, необходимо создать public методы getter и setter (например getName(), setName($name)), чтобы получить доступ к его свойствам в остальном коде приложения. Команда «php bin/console doctrine:generate:entities AppBundle/Entity/Product» может автоматически генерировать эти шаблонные методы. Эта команда гарантирует, что все геттеры и сеттеры будут созданы для класса. Это безопасная команда – имеется возможность запускать её неограниченное количество раз: она генерирует только геттеры и сеттеры, которые не существуют (т. е. не заменяют существующие методы). Генератор сущности Doctrine создает простые геттеры/сеттеры. При необходимости можно добавить любую логику в соответствии с потребностями создаваемого приложения.

Для автоматического создания всех таблиц базы данных, необходимых для каждого известного объекта используется команда «php bin/console doctrine:schema:update –force». Эта команда сравнивает, как должна выглядеть база данных (на основе информации о сопоставлении сущностей) с тем, как она выглядит на самом деле, и выполняет инструкции SQL, необходимые для обновления схемы базы данных. Другими словами, если добавить новое свойство с метаданными сопоставления в класс сущности и запустить эту команду, она выполнит инструкцию «ALTER TABLE», необходимую для добавления этого нового столбца в существующую таблицу.

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

Независимо от того, используются ли возможности миграции, команда «doctrine:schema:update» должна использоваться только во время разработки. Она не должна использоваться в производственной среде.

После того как объект стал соответствовать таблице, появляется возможность сохранять объект в базе данных. Внутри контроллера это можно сделать, как указано в листинге 6.

<?// src/AppBundle/Controller/DefaultController.php use AppBundle\Entity\Product;use Symfony\Component\HttpFoundation\Response;use Doctrine\ORM\EntityManagerInterface;use Doctrine\Common\Persistence\ManagerRegistry; public function createAction(EntityManagerInterface $em){ // создание нового объекта класса Product $product = new Product(); // устанавливает значения свойств $product->setName('Keyboard'); $product->setPrice(19.99); $product->setDescription('Ergonomic and stylish!'); // сообщение Doctrine, о намерении сохранить объект $em->persist($product); // фактическое выполнение запроса INSERT $em->flush(); // возвращение ответа return new Response('Saved new product with id '.$product->getId());}

Листинг 6. Сохранение объекта в базу данных

Метод flush() использует механизмы кэширования и подготавливает единый запрос к базе в независимости от количества создаваемых объектов.

Для получения объекта из базы данных используются механизмы, аналогичные тем, что указаны в листинге 7.

<?use Doctrine\ORM\EntityManagerInterface; public function showAction($productId, EntityManagerInterface $em){ // получение репозитория объекта и запрос сущности по её ID $product = $em->getRepository('AppBundle:Product') ->find($productId); // вывод сообщения об ошибке в случае отсутствия сущности с указанным ID if (!$product) { throw $this->createNotFoundException( 'No product found for id '.$productId ); }}

Листинг 7. Получение сущности из базы данных

Для запроса объектов из базы можно использовать различные методы репозитория. Таковыми могут быть как стандартные методы (findBy, find, findAll, findOneBy и т. д.), так и методы, которые определены в репозитории сущности самим разработчиком.

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

Если количество запросов к базе данных слишком велико, значок станет желтым, указывая на то, что что-то может быть неверным. При нажатии на значок, можно открыть Symfony Profiler и посмотреть конкретные запросы, которые были выполнены.

После получения объекта, имеется возможность его обновить, как это указано в листинге 8.

<?use Doctrine\ORM\EntityManagerInterface; public function updateAction($productId, EntityManagerInterface $em){ // получение репозитория объекта и запрос сущности по её ID $product = $em->getRepository('AppBundle:Product')->find($productId); // вывод сообщения об ошибке в случае отсутствия сущности с указанным ID if (!$product) { throw $this->createNotFoundException( 'No product found for id '.$productId ); } // установка нового значения свойства $product->setName('New product name!'); // фактическое выполнение запроса INSERT $em->flush(); // перенапрваление на главную страницу return $this->redirectToRoute('homepage');}

Листинг 8. Обновление объекта в базе данных

Для удаления объекта используются метод $em->remove(). Для фактического удаления используется метод $em->flush();

В случае необходимости использования более сложных запросов используется DQL – родной язык Doctrine. Он очень схож с языком SQL, за одним большим отличием – при построении запросов необходимо думать с точки зрения выбора объектов PHP, а не строк в базе данных. Такие запросы можно создавать непосредственно внутри методов классов контроллеров, но для организации Doctrine предоставляются специальные классы репозитория, которые позволяют хранить всю логику запросов в одном централизованном месте.

<?

$query = $em->createQuery(

'SELECT p

FROM AppBundle:Product p

WHERE p.price > :price

ORDER BY p.price ASC'

)->setParameter('price', 19.99);

$products = $query->getResult();

Листинг 9. Пример построения запроса на языке DQL

Doctrine позволяет сосредоточиться на объектах и на том, как они используются в приложении, и обеспечивает сохранность базы данных. Это связано с тем, что Doctrine позволяет использовать любой объект PHP для хранения данных и полагается на информацию метаданных для сопоставления данных объекта с конкретной таблицей базы данных.

Маршрутизация

Наличие человекопонятных URL-адресов (ЧПУ) является абсолютной необходимостью для любого серьезного веб-приложения. Например, index.php?article_id=57 проигрывает по сравнению с /read/intro-to-symfony.

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

# app/config/routing.yml

blog_list:

path: /blog

defaults: { _controller: AppBundle:Blog:list }

blog_show:

path: /blog/{slug}

defaults: { _controller: AppBundle:Blog:show }

Листинг 10. Пример определения маршрутов в формате YAML

При создании маршрутов имеется возможность определения параметров, передаваемых в URL, задавать значения по умолчанию для этих параметров, производить их валидацию по регулярному выражению, указывать допустимые типы запросов к контроллеру ($_GET, $_POST), сопоставлять метод контроллера, устанавливать языковые стандарты по запросу. Имя маршрута не может начинаться с цифры, а также быть длиннее 32 символов.

Symfony загружает все маршруты для приложения из одного файла конфигурации маршрутизации: app/config/routing.yml. Но изнутри этого файла можно загружать любые другие файлы маршрутизации. Фактически, по умолчанию Symfony загружает конфигурацию маршрута аннотаций из каталога бандла Controller/, при использовании YAML, XML, PHP из каталога Recourses/config.

Контроллеры

Контроллер - это созданная функция PHP, которая считывает информацию из Request объекта Symfony и создает и возвращает Response объект. Ответ может быть HTML-страницей, JSON, XML, файлом, перенаправлением, ошибкой 404 или чем-либо еще. Контроллер выполняет произвольную логику, необходимую приложению для отображения содержимого страницы. Он может считывать информацию из запроса, загружать ресурс базы данных, отправлять электронную почту или задавать информацию на сеансе пользователя. Но во всех случаях контроллер в конечном итоге возвращает Response объект, который будет доставлен обратно клиенту.

Для удобства Symfony поставляется с двумя дополнительными базовыми Controller и AbstractController классами. Это позволяет расширить или получить доступ к нескольким вспомогательным методам. Разница между Controller и AbstractController в том, что при расширении AbstractController нет возможности получить доступ к сервисам напрямую через $this->get() или $this->container->get().

Базовый класс содержит следующие методы для удобного определения метода контроллера:

· Перенаправление - return $this->redirectToRoute('homepage');

· Рендер шаблона - return $this->render(index.html.twig', array('name' => $name));

· Получение сервисов в качестве аргументов контроллера. Symfony поставляется с большим количеством полезных объектов, называемых сервисы. Они используются для создания шаблонов, отправки электронных писем, запросов к базе данных и любой другой «работы». Для получения нужного сервиса в контроллере, необходимо указать в качестве аргумента метода контроллера переменную нужного класса или интерфейса. Для получения полного списка доступных сервисов используется команда «php bin/console debug:container –types».

· Доступ к контейнеру - $mailer = $this->get('mailer');

· Отображение ошибки 404. throw $this->createNotFoundException('The product does not exist');

· Управление сессиями - $session->set('foo', 'bar');

· Flash-сообщения - $this->addFlash('notice', 'Your changes were saved!');

· Возвращение JSON-объектов - return $this->json(array('username' => 'jane.doe'));

· Возвращение файлов - return $this->file('/path/to/some_file.pdf');

· Объект Request в качестве аргумента контроллера. Используется для получения данных из массивов $_POST, $_GET, а также значений определённых в маршрутизации параметров.

Request класс имеет несколько открытых свойств и методов, которые возвращают любую необходимую информацию о запросе.

Как и объект Request, Response объект также имеет публичное свойство headers. Он имеет методы для получения и настройки заголовков ответов. Имена заголовков нормализуются так, что использование Content-Type эквивалентно content-type или даже content_type.

Единственное требование для контроллера - вернуть Response объект. Response класс является абстракцией вокруг ответа HTTP – текстовое сообщение, заполненное заголовками и содержанием, которое отправляется обратно клиенту.

Шаблонизатор Twig

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

На самом деле контроллер делегирует большую часть тяжелой работы в другие места, чтобы код можно было тестировать и повторно использовать. Когда контроллер должен сгенерировать HTML, CSS или любой другой контент, он передает работу в механизм шаблонов. Шаблон - это простой текстовый файл, который может генерировать любой текстовый формат (HTML, XML, CSV, LaTeX и т. д.) Наиболее знакомым типом шаблона является PHP-шаблон - текстовый файл, обработанный PHP, который содержит сочетание текста и кода PHP. Но Symfony предлагает собственный язык шаблонов под названием Twig. Twig позволяет писать сжатые, читаемые шаблоны, которые более дружелюбны к веб-дизайнерам и, в некоторых аспектах, более мощные, чем шаблоны PHP.

Twig определяет три типа специального синтаксиса:

{{ ... }}

«Вывести что-то»: печатает переменную или результат выражения в шаблоне.

{% ... %}

«Сделать что-то»: тег, который управляет логикой шаблона; Он используется для выполнения таких операторов, как, например, for-loops.

{# ... #}

«Комментировать что-то»: это эквивалент /* comment */синтаксиса PHP. Он используется для добавления одиночных или многострочных комментариев. Содержание комментариев не включено в отображаемые страницы.

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

Код Twig похож на PHP-код, с небольшими отличиями. В листинге 11 используется стандартный тег for и функция cycle() для печати десять div тегов, с чередованием значений «odd» и «even».

{% for i in 1..10 %}

<div class="{{ cycle(['even', 'odd'], i) }}">

{# some HTML here #}

</div>

{% endfor %}

Листинг 11. Пример синтаксиса шаблонизатора Twig

Шаблоны Twig должны быть простыми и не будут обрабатывать теги PHP. Система шаблонов Twig предназначена для отображения вида, а не программной логики.

Twig также может делать то, что не может сделать PHP, например, управление пробелами, песочница, автоматическое экранирование HTML, ручное контекстное выходное экранирование и включение пользовательских функций и фильтров, которые влияют только на шаблоны. Twig содержит возможности, которые упрощают и создание шаблонов писем.

Twig обладает высоким быстродействием, так как каждый шаблон автоматически компилируется в собственный PHP-класс и кэшируется. Во время разработки Twig повторно компилирует шаблоны после внесения каких-либо изменений.

Чаще всего шаблоны в проекте имеют общие элементы, такие как верхний колонтитул, нижний колонтитул, боковая панель и т. д. В Symfony эта проблема рассматривается по-разному: шаблон может быть интегрирован с другим. Это работает точно так же, как и классы PHP: наследование шаблонов позволяет создать базовый шаблон «макета», содержащий все общие элементы сайта, определенные как блоки с помощью тега {% block name%}text{% endblock%} («PHP-класс с базовыми методами»). Дочерний шаблон может расширять базовый макет с помощью тега {% extends %} и переопределять любые его блоки («дочерний класс PHP, который переопределяет определенные методы его родительского класса»).

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

· app/Resources/views/

Views Каталог приложения может содержать базовые шаблоны приложений (например, макеты приложения и шаблоны пакета приложений), а также шаблоны, которые переопределяют шаблоны бандлов сторонних разработчиков.

· vendor/path/to/Bundle/Resources/views/

Каждый сторонний бандл содержит свои шаблоны в своем Resources/views/ каталоге (и подкаталогах).

При необходимости включить код шаблона в другой шаблон используется функция {{ include() }}. Для вывода ссылки на страницу из маршрутизатора функция {{ path(имя_маршрута, {имя параметра, значение_параметра}) }}.

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

Генерация форм и валидация

Работа с форматами HTML является одной из наиболее распространенных и сложных задач для веб-разработчика. Symfony включает компонент Form, который упрощает работу с формами. Компонент Symfony Form представляет собой отдельную библиотеку, которая может использоваться вне проектов Symfony.

После создания класса сущности В Symfony имеется возможность создания объекта формы, а затем его отображение в шаблоне.

<?

namespace AppBundle\Controller;

use AppBundle\Entity\Task;

use Symfony\Bundle\FrameworkBundle\Controller\Controller;

use Symfony\Component\HttpFoundation\Request;

use Symfony\Component\Form\Extension\Core\Type\TextType;

use Symfony\Component\Form\Extension\Core\Type\DateType;

use Symfony\Component\Form\Extension\Core\Type\SubmitType;

class DefaultController extends Controller

{

public function newAction(Request $request)

{

// Создание объекта сущности

$task = new Task();

$task->setTask('Write a blog post');

$task->setDueDate(new \DateTime('tomorrow'));

// Генерация формы

$form = $this->createFormBuilder($task)

->add('task', TextType::class)

->add('dueDate', DateType::class)

->add('save', SubmitType::class, array('label' => 'Create Post'))

->getForm();

// Отображение шаблона

return $this->render('default/new.html.twig', array(

'form' => $form->createView(),

));

}

}

Листинг 12. Создание объекта формы

Создание формы требует относительно небольшого кода, потому что объекты формы Symfony построены с помощью «конструктора форм». Задача создателя формы - написать простой генератор формы, форма сгенерируется автоматически.

В примере на листинге 12 добавлено два поля в форму – task и dueDate - соответствующие свойствам task и dueDate свойствам Task класса. Так же назначается каждому свойству «тип» (например, TextType и DateType), представленный его полным именем класса. Помимо прочего, он определяет, какой HTML-тег отображается для этого поля. Также добавляется кнопка отправки с пользовательской надписью для отправки формы на сервер.

Когда форма была создана, следующим шагом будет ее рендеринг. Это делается путем передачи объекта формы «view» в шаблон и с помощью набора вспомогательных функций формы. Для отображения полной формы необходимы три строки в Twig:

· form_start(form)

Отображает начальный тег формы, включая атрибут enctype при использовании загрузки файлов.

· form_widget(form)

Отображает все поля, включая сам элемент поля, метку и любые сообщения об ошибках проверки для поля.

· form_end(form)

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

По умолчанию форма отправит POST запрос обратно на тот же контроллер, который отображает её. Для обработки полученных данных используется код, указанный в листинге 13.

// Отправка в форму объекта Request

$form->handleRequest($request);

if ($form->isSubmitted() && $form->isValid()) { // Получение данных из формы $task = $form->getData(); // Сохранение полученных данных в базе $em->persist($task); $em->flush(); return $this->redirectToRoute('task_success');}

Листинг 13. Получение и обработка данных из формы

В Symfony валидация применяется к базовому объекту. Другими словами, вопрос заключается не в том, является ли «форма» валидной, а является ли объект валидным после того, как форма применила к нему предоставленные данные. Вызов $form->isValid() - это сокращение, которое запрашивает у объекта, имеет ли он валидные данные.

Проверка выполняется путем добавления в класс сущности набора правил (называемых ограничениями). Это может быть реализовано, как с помощью аннотация, так и файлов YAML, XML и PHP. Валидация производится с помощью классов внутри пространства имён Symfony\Component\Validator\Constraints. Доступные ограничения:

Основные ограничения

· NotBlank

· Blank

· NotNull

· IsNull

· IsTrue

· IsFalse

· Type

Строковые ограничения

· Length

· Email

· Url

· Regex

· Ip

· Uuid

Числовые ограничения

· Range

Сравнительные ограничения

· EqualTo

· NotEqualTo

· IdenticalTo

· NotIdenticalTo

· LessThan

· LessThanOrEqual

· GreaterThan

· GreaterThanOrEqual

Ограничения по дате

· Date

· DateTime

· Time

Ограничения коллекции

· Choice

· Collection

· Count

· UniqueEntity

· Language

· Locale

· Country

Файловые ограничения

· File

· Image

Финансовые и числовые ограничения

· Bic

· CardScheme

· Currency

· Luhn

· Iban

· Isbn

· Issn

Другие ограничения

· Callback

· Expression

· All

· UserPassword

· Valid

При выводе формы имеется возможность добавления атрибутов для валидации формы средствами HTML 5, указания типов полей (textarea, email, money, url, password, choice, date, file и т. д.), надписи. При отсутствии фактического указания этих параметров, Symfony пытается «угадать» их значение. Если это происходит некорректно, необходимо вручную переопределить данные параметры.

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

Безопасность

Организация безопасности в Symfony происходит в три этапа:

1. Первоначальная настройка security.yml (аутентификация);

2. Запрет доступа к приложению (авторизация);

3. Получение текущего объекта пользователя.

Система безопасности настраивается в файле app/config/security.yml. Конфигурация по умолчанию представлена в листинге 14.

security:

providers:

in_memory:

memory: ~

firewalls:

dev:

pattern: ^/(_(profiler|wdt)|css|images|js)/

security: false

main:

anonymous: ~

Листинг 14. Конфигурация безопасности по умолчанию

В данном файле определяются все настройки безопасности приложения. Например, ссылка, на которую будет перенаправлен пользователь при попытке входа на защищённую страницу, ссылка на страницу выхода, разрешение анонимного пользователя, параметры кодирования пароля и т. д.

На следующем этапе в параметре access_control указывается список защищённых маршрутов и права доступа к ним, а в параметре role_hierarchy категории групп прав, иерархия ролей.

Одним из основных параметров является «users», который определяет, каким образом будет задана информация о пользователях (непосредственно из файла или конкретной сущности). Внутри контроллера и шаблона имеется возможность проверить права текущего пользователя, проверить, является ли он авторизованным, и, в зависимости от этого, выполнять различные действия.

Symfony предоставляет возможность создания собственных обработчиков событий при возникновении различных событий связанных с безопасностью (авторизация, выход, регистрация, ввод неверного пароля и т. д.)

Сервисы

Symfony Framework наполнен полезными объектами: объект «Mailer» помогает отправлять электронные письма, а другой объект может помочь сохранить данные в базе данных. Почти все, что делает приложение фактически выполняется одним из этих объектов. При установке нового бандла увеличивается количество доступных объектов.

В Symfony эти объекты называются сервисами, и каждый сервис находится внутри особого объекта, называемого контейнером сервисов. После получения контейнера сервисов, можно получить сервис, используя идентификатор эго сервиса с помощью метода get(): «$logger = $container->get('logger');»

Контейнер позволяет централизовать способ конструирования объектов. Для получения полного списка доступных сервисов из контейнера необходимо ввести консольную команду: «php bin/console debug:container».

Собственные сервисы по умолчанию располагаются в папке Service в каталоге бандла. После его создания необходимо зарегистрировать сервис в конфигурационном файле. При необходимости использования другого сервиса внутри текущего, в конструкторе сервиса указывается аргумент с типом необходимого сервиса, что также нужно указать в файле конфигурации.

При запросе сервиса, контейнер создает новый объект и возвращает его. Но если сервис не был запрошен, он никогда не будет сконструирован. Это экономит память и скорость. Он также создается только один раз: один и тот же экземпляр возвращается каждый раз, когда запрашивается.

Консольные команды

Symfony Framework предоставляет множество команд через bin/console скрипт (например, команда bin/console cache:clear). Эти команды создаются с помощью компонента Console. Он так же используется для создания пользовательских команд.

Команды определяются в классах, которые должны быть созданы в директории Command бандла (например, AppBundle\Command), и их имена должны заканчиваться суффиксом Command.

Внутри данных классов имеется возможность получения сервисов из контейнера, добавление аргументов (методом addArgument), вывод в консоль (методом writeln), определения названия (setName), описания (setDescription) и помощи (setHelp) по команде.

Команды имеют три метода жизненного цикла, которые вызываются при выполнении команды:

initialize() (необязательный)

Этот метод выполняется до interact() и execute() методов. Его основная цель - инициализировать переменные, используемые в остальных к

Наши рекомендации