Урок 2. Компоненты Symfony
Опубликовано пн, 09/01/2017 - 23:58
Рассмотрим все компоненты симфони, которые вошли в ядро, а также разберемся для чего они нужны и за что отвечают.
Содержание
- Компоненты Symfony
- BrowserKit
- ClassLoader
- Console
- CssSelector
- Debug
- DependencyInjection
- DomCrawler
- EventDispatcher
- HttpFoundation
- HttpKernel
- Symfony Polyfill
- Process
- PSR-7 Bridge
- Routing
- Serializer
- Translation
- Validator
- Yaml
- Домашнее задание
Компоненты Symfony
BrowserKit
Симулирует[1] поведение веб браузера, позволяет делать запросы, кликать на ссылки и сабмитать формы программно.
ClassLoader
Компонент[2], позволяющий производить автозагрузку классов и кэшировать их для улучшения производительности. Symfony предоставляет три автозагрузчика (PSR - PHP Standart Recommendations[3]):
- PSR-0 Class Loader[4] — загружает классы, которые следуют PSR-0 стандарту автозагрузки.
- PSR-4 Class Loader[5] — загружает классы, которые следуют PSR-4 стандарту автозагрузки.
- MapClassLoader[6] — загружает классы, используя статический мапинг имени класса с его путем.
Пример использования PSR-0 Class Loader
1 2 3 4 5 6 7 8 9 |
// Регистрация автозагрузчика. use Composer\Autoload\ClassLoader; $class = 'Not\\A\\Class'; $loader = new ClassLoader(); $loader->addClassMap(array($class => __FILE__)); $loader->register(); // Выполнение каких-либо действий ... // Отмена дополнительного автозагрузчика. $loader->unregister(); |
Пример с PSR-4 Class Loader
1 2 3 4 |
use Symfony\Component\ClassLoader\Psr4ClassLoader; $loader = new Psr4ClassLoader(); $loader->addPrefix('Symfony\\Component\\Serializer\\', 'path/to/symfony/serializer'); $loader->register(); |
Пример с MapClassLoader
1 2 3 4 5 6 |
use Symfony\Component\ClassLoader\MapClassLoader; $map = array( 'Example' => '/path/to/Example', ); $loader = new MapClassLoader($map); $loader->register(); |
Console
Позволяет создавать команды командной строки[7]. Консольные команды могут использованы для выполнения каких либо повторяющихся задач, например, крон тасков, импортов или других batch операций.
Пример использования
1 2 3 4 5 |
use Symfony\Component\Console\Application; $app = new Application(); // Регистрация некой команды. $app->add(new SimpleCommand()); $app->run(); |
CssSelector
Конвертирует CSS селекторы в Xpath выражения[8]. Xpath выражения невероятно гибкие. Практически во всех случаях Xpath сможет найти то, что вам требуется. Но в то же время они довольно сложны в построении. Даже на первый взгляд простой поиск (найти элементы по определенному классу) может потребовать длинного и сложного выражения. Существуют ограничения: не все css селекторы могут быть сконвертированы в Xpath (псевдоклассы; псевдоэлементы; селекторы, основанные на действиях пользователя и т.д.). Полный перечень того, что не может быть сконвертировано вы найдете в документации по ссылке[8].
Пример использования.
1 2 3 |
use Symfony\Component\CssSelector\CssSelectorConverter; $convert = new CssSelectorConverter(); $output = $convert->toXPath('form div span'); |
Получаем результат
1 |
descendant-or-self::form/descendant-or-self::*/div/descendant-or-self::*/span |
Debug
Позволяет упростить отладку кода PHP[9]. Предоставляет три класса ErrorHandler, ExceptionHandler и Debug.
- ErrorHandler — ловит PHP ошибки и конвертирует их в исключения.
- ExceptionHandler — ловит неперехваченные исключения PHP и выводит их в красивом виде.
- Debug — регистрирует все инструменты дебага.
Пример
1 2 3 4 5 6 7 8 9 10 11 12 13 |
use Symfony\Component\Debug\ErrorHandler; use Symfony\Component\Debug\ExceptionHandler; ErrorHandler::register(); try { trigger_error('Here is some error'); } catch (\Exception $e) { ExceptionHandler::register(); $handler = new ExceptionHandler(); $handler->handle($e); return $e->getMessage(); } |
Вывод
или такой пример
1 2 3 4 5 6 |
use Symfony\Component\Debug\ErrorHandler; use Symfony\Component\Debug\ExceptionHandler; ErrorHandler::register(); ExceptionHandler::register(); function_not_exists(); |
Предыдущий пример через Debug можно было бы записать так
1 2 3 |
use Symfony\Component\Debug\Debug; Debug::enable(); function_not_exist(); |
Результат
DependencyInjection
DependencyInjection (service container, dependency injection container или контейнер зависимостей) — компонент, который позволяет стандартизировать и централизовать пути к объектам, определенным в приложении[10]. Сервис контейнер — это PHP объект, который управляет инстанциированием сервисов (т.е. объектами).
Конфигурация сервисов в Drupal 8 находится в формате YAML, в файлах MODULE.services.yml.
Пример конфигурации Ban модуля, ban.services.yml
1 2 3 4 5 6 7 8 9 10 11 12 13 |
services: ban.ip_manager: class: Drupal\ban\BanIpManager arguments: ['@database'] tags: - { name: backend_overridable } ban.middleware: class: Drupal\ban\BanMiddleware arguments: ['@ban.ip_manager'] tags: # Ensure to come before page caching, so you don't serve cached pages to # banned users. - { name: http_middleware, priority: 250 } |
В данном конфиге объявлено два сервиса, каждый из которых имеет свой класс, описывающий логику работы. Когда вы обращаетесь за нужный сервисом, контейнер создает объект и его возвращает. Это еще одно существенное преимущество сервис контейнера. Если сервис не вызывается, то он и не создается, не тратя память впустую и ухудшая производительность.
DomCrawler
Облегчает DOM навигацию для HTML и XML документов[11]. Если вы знакомы с jQuery, то DomCrawler — это PHP эквивалент. Позволяет искать элементы с помощью методов filter() и filterXpath(). Первый принимает селектор в формате CSS, второй - в формате Xpath выражения.
Пример использования.
1 2 3 4 5 |
use Symfony\Component\DomCrawler\Crawler; $html = '<html><title>HTML TITLE</title><body>HTML BODY</body></html>'; $crawler = new Crawler(); $crawler->addContent($html); print $crawler->filter('body')->text(); |
выведет
1 |
HTML BODY |
Тот же пример с использованием filterXpath().
1 2 3 4 5 |
use Symfony\Component\DomCrawler\Crawler; $html = '<html><title>HTML TITLE</title><body>HTML BODY</body></html>'; $crawler = new Crawler(); $crawler->addContent($html); print $crawler->filterXPath('descendant-or-self::body')->text(); |
EventDispatcher
Компонент, предоставляющий инструменты, которые в свою очередь, позволяют компонентам вашего приложения коммуницировать друг с другом, отправляя события и прослушивая их[12]. Реализует паттерн посредник (Mediator).
Посредник (англ. Mediator) — поведенческий шаблон проектирования, обеспечивающий взаимодействие множества объектов, формируя при этом слабую связанность и избавляя объекты от необходимости явно ссылаться друг на друга[13].
Dispatcher — центральный объект во всей event dispatcher системе. После его инстанцирования, к нему подключается множество слушателей. Когда событие проходит через dispatcher, он оповещает всех слушателей, подписанных на это событие.
Пример. Создание экземпляра dispatcher
1 2 |
use Symfony\Component\EventDispatcher\EventDispatcher; $dispatcher = new EventDispatcher(); |
Подключение слушателя
1 2 |
$listener = new ExampleListener(); $dispatcher->addListener('example.action', array($listener, 'onFooAction')); |
Метод addListener() принимает три аргумента:
- имя события, должно быть строкой
- callable метод класса слушателя
- необязательный аргумент - число, которое определяет приоритет вызова слушателя. По умолчанию 0.
В свою очередь ExampleListener класс имеет такое содержимое
1 2 3 4 5 6 7 8 |
use Symfony\Component\EventDispatcher\Event; class ExampleListener { // ... public function onFooAction(Event $event) { // ... какие-то действия } } |
HttpFoundation
Компонент, определяющий объектно-ориентированный слой для HTTP спецификации[14]. В PHP запрос представлен некоторыми глобальными переменными ($_GET, $_POST, $_FILES, $_COOKIE, и т.д.), а ответ генерируется некоторыми функциями (echo, header() и т.д.)
Данный компонент призван заменить эти глобальные переменные и функциями одним объектно-ориентированный объектом. Содержит классы запроса (Request) и ответа (Response). Более подробно тема запросов и ответов будет рассмотрена в следующем уроке.
HttpKernel
Как уже упоминалось в первом, ознакомительном уроке, данный компонент необходим для стандартизации процесса конвертации запроса в ответ с помощью EventDispatcher компонента[15].
HttpKernel предоставляет интерфейс, который формализует процесс создания запроса и ответа. Компонент описывает "правила" данного процесса, оставляя реализацию за системой, фреймворком, в котором он используется.
Symfony Polyfill
Symfony Polyfill[16] — это проект, цель которого обеспечить портируемость и совместимость некоторых фич, найденных в последних версиях PHP. Список расширений, используемых в Drupal 8:
- Symfony Polyfill/APCu[17] — предоставляет apcu_* функции, а также APCUIterator класс. APCu - это APC (Alternative PHP Cache) без кеширования опкода.
- Symfony Polyfill/Iconv[18] — предоставляет нативные iconv функции PHP. Позволяет менять кодировку строки на иную из доступного списка.
- Symfony Polyfill/Mbstring[19] — предоставляет реализацию Mbstring расширения.
- Symfony Polyfill/Php54[20] — компонент, который предоставляет функции недоступные в релизе PHP 5.4, а именно: trait_exists, class_uses, hex2bin, session_register_shutdown.
- Symfony Polyfill/Php55[21] — позволяет пользоваться функциями, недоступными для релиза PHP версии 5.5, а именно: boolval, json_last_error_msg, array_column, hash_pbkdf2, password_* functions.
Process
Компонент, выполняющий команды в sub-процессах[22].
Пример:
1 2 3 4 |
use Symfony\Component\Process\Process; $process = new Process('cd /tmp/; ls -al'); $process->run(); print_r($process->getOutput()); |
С помощью команд ‘cd /tmp/; ls -al’ — переходим в tmp папку корневой директории сервера и выводим ее содержимое. Результат приведен ниже
PSR-7 Bridge
PSR-7 Bridge[23] преобразует HttpFoundation объекты в объекты, реализующие стандарт PSR-7 и наоборот, объекты определенные по PSR-7 в HttpFoundation объекты.
Routing
Преобразовывает HTTP запрос в вызов определенной функции, подобно hook_menu()[24]. Мапит HTTP запрос на перечень конфигурационных переменных.
Serializer
Предназначен для конвертации объектов в специальный формат (XML, JSON, т.д.) и обратно[25]. Упрощенная схема, по которой работает компонент Serializer приведена ниже
Кодировщики (Encoders) конвертируют массивы в специальные форматы и обратно. В свою очередь нормализаторы (Normalizers) работают с преобразованием объектов в массивы и наоборот.
Translation
Компонент содержит инструменты для интернационализации приложения[26]. Ключевым классом является Translator. Может подгружать переводы с различных источников: массивов, json, yml файлов, csv, php, xml и т.д. Переводы хранятся в каталогах сообщений внутри класса Translator.
Пример использования
1 2 3 4 5 6 7 |
use Symfony\Component\Translation\Loader\ArrayLoader; use Symfony\Component\Translation\Translator; $translator = new Translator('ru_RU'); $translator->addLoader('array', new ArrayLoader()); $translator->addResource('array', array( 'user' => 'пользователь', ), 'ru_RU'); |
Перевод слова user
1 |
echo $translator->trans('user'); |
Validator
Валидация — это довольно общая задача. Например, для полей с датами нужно проверять корректность ввода даты, для полей, которые хранят числовые значения - проверять что в них записаны именно числа, для строковых - строки и т.д. Validator[27] — компонент, который предоставляет инструменты для того, чтобы сделать данную процедуру простой и прозрачной. Важным компонентом является так называемые Constraints — классы, наследуемые от абстрактного класса Constraint. Каждый такой класс отвечает за проверку определенного формата данных и не только. Из коробки доступно большое количество constraints: базовые (NotBlank, Blank, IsTrue, IsNull и т.д.), строковые, числовые, файловые и т.д.
Для примера проверим корректность даты
1 2 3 4 5 6 |
use Symfony\Component\Validator\Constraints\Date; use Symfony\Component\Validator\Validation; $validator = Validation::createValidator(); $constraint = new Date(); $errors = $validator->validate('2016-99-99', $constraint); return !empty($errors->count()) ? t('Date is invalid') : t('Date is valid'); |
Получаем
1 |
Date is invalid |
Yaml
Yaml[28] — загружает и парсит файлы в формате yml. Причины по которым в качестве хранилища конфигов, а также файлов экспорта/импорта был выбран yml формат:
- Быстрая скорость обработки данных
- Надежный анализатор разбирающий большое множество Yaml спецификаций
- Удобен для чтения и внесения изменений.
- Содержит понятные сообщения об ошибках
- Поддержка типов: поддерживает большинство Yaml встроенных типов данных - даты, числа, булевские значения и т.д.
- Имеет полную поддержку ссылок & и алиасов (*)
Пример использования. Предположим у нас есть некий файлик в формате YAML - example.yml.
Содержимое example.yml
1 2 |
example.content: path: '/example' |
Мы можем его распарсить следующим образом
1 2 |
use Symfony\Component\Yaml\Yaml; $content = Yaml::parse(file_get_contents('path_to_file_example.yml')); |
В результате в переменной $content будет массив данных из этого файла
С помощью данного компонента можно также записывать данные в формат YAML.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 |
use Symfony\Component\Yaml\Yaml; $example = array( 'one' => array( 'one.one' => 11, 'one.two' => 12, ), 'two' => array( 'two.one' => array( 'two.one.one' => 211, ), ), 'three' => 3, ); $yml = Yaml::dump($example); file_put_contents('path_to_file_example.yml', $yml); |
В результате содержимое файлы example.yml будет следующим
1 2 3 4 5 6 |
one: one.one: 11 one.two: 12 two: two.one: { two.one.one: 211 } three: 3 |
Домашнее задание
Необходимо установить/развернуть Drupal 8 на локальном сервере, т.к. в последующих уроках приступим к написанию собственного модуля. Разворачивать можно по аналогии с 7-ой версией по статьям Установка и настройка VirtualBox и Установка Drupal на VirtualBox. Версию ubuntu лучше ставить от 14 и выше, версию PHP не ниже 5.6.
Дополнительная информация по статье
- http://symfony.com/doc/current/components/browser_kit.html - о BrowserKit из документации Symfony.
- https://symfony.com/doc/current/components/class_loader.html - о ClassLoader из документации Symfony.
- http://www.php-fig.org/psr - о PHP стандартах PSR.
- http://www.php-fig.org/psr/psr-0/ - о PSR-0.
- http://www.php-fig.org/psr/psr-4 - о PSR-4.
- https://symfony.com/doc/current/components/class_loader/map_class_loader.html - о MapClassLoader из документации Symfony.
- https://symfony.com/doc/current/components/console.html - о Console из документации Symfony.
- https://symfony.com/doc/current/components/css_selector.html - о CssSelector из документации Symfony.
- http://symfony.com/doc/current/components/debug.html - о Debug из документации Symfony.
- https://symfony.com/doc/current/components/dependency_injection/index.html - DependencyInjection из документации Symfony.
- http://symfony.com/doc/current/components/dom_crawler.html - о DomCrawler из документации Symfony.
- https://symfony.com/doc/current/components/event_dispatcher/index.html - о EventDispatcher из документации Symfony.
- https://ru.wikipedia.org/wiki/Посредник_(шаблон_проектирования) - паттерн Посредник на wiki
- http://symfony.com/doc/current/components/http_foundation.html - о HttpFoundation из документации Symfony.
- http://symfony.com/doc/current/components/http_kernel.html - о HttpKernel из документации Symfony.
- https://github.com/symfony/polyfill - Symfony Polyfill на гитхабе.
- https://github.com/symfony/polyfill/blob/master/src/Apcu/README.md - о Symfony Polyfill / APCu.
- https://github.com/symfony/polyfill/blob/master/src/Iconv/README.md - о Symfony Polyfill / Iconv.
- https://github.com/symfony/polyfill-mbstring - о Symfony Polyfill / Mbstring.
- https://github.com/symfony/polyfill-php54 - о Symfony Polyfill / Php54.
- https://github.com/symfony/polyfill-php55 - о Symfony Polyfill / Php55.
- https://symfony.com/doc/current/components/process.html - о Process из документации Symfony.
- http://symfony.com/doc/current/request/psr7.html - о PSR-7 Bridge из документации Symfony.
- https://symfony.com/doc/current/components/routing/index.html - о Routing из документации Symfony.
- https://symfony.com/doc/current/components/serializer.html - о Serializer из документации Symfony.
- https://symfony.com/doc/current/components/translation/index.html - о Translation из документации Symfony.
- https://symfony.com/doc/current/book/validation.html - о Validator из документации Symfony.
- https://symfony.com/doc/current/components/yaml/index.html - о YAML из документации Symfony.
- Версии программных продуктов, используемых в статье: Drupal 8.2.4