Учебники

Symfony — Продвинутые понятия

В этой главе мы узнаем о некоторых продвинутых концепциях в среде Symfony.

HTTP-кэш

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

Cache Item

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

Кэш-адаптер

Адаптер кеша — это реальный механизм для хранения товара в магазине. Хранилище может быть памятью, файловой системой, базой данных, Redis и т. Д. Компонент Cache предоставляет интерфейс AdapterInterface, через который адаптер может хранить элемент кэша в внутреннем хранилище. Есть много встроенных адаптеров кеша. Немногие из них следующие:

  • Адаптер Array Cache — элементы кэша хранятся в массиве PHP.

  • Адаптер кеша файловой системы — элементы кеша хранятся в файлах.

  • Адаптер кэша файлов PHP — элементы кэша хранятся в виде файлов php.

  • APCu Cache Adapter — элементы кэша хранятся в общей памяти с использованием расширения PHP APCu.

  • Redis Cache Adapter — элементы кэша хранятся на сервере Redis.

  • PDO и Doctrine DBAL Cache Adapter — элементы кэша хранятся в базе данных.

  • Цепной адаптер кэша — объединяет несколько адаптеров кэша для целей репликации.

  • Proxy Cache Adapter — элементы кэша хранятся с использованием стороннего адаптера, который реализует CacheItemPoolInterface.

Адаптер Array Cache — элементы кэша хранятся в массиве PHP.

Адаптер кеша файловой системы — элементы кеша хранятся в файлах.

Адаптер кэша файлов PHP — элементы кэша хранятся в виде файлов php.

APCu Cache Adapter — элементы кэша хранятся в общей памяти с использованием расширения PHP APCu.

Redis Cache Adapter — элементы кэша хранятся на сервере Redis.

PDO и Doctrine DBAL Cache Adapter — элементы кэша хранятся в базе данных.

Цепной адаптер кэша — объединяет несколько адаптеров кэша для целей репликации.

Proxy Cache Adapter — элементы кэша хранятся с использованием стороннего адаптера, который реализует CacheItemPoolInterface.

Кеш-пул

Cache Pool — логическое хранилище элементов кеша. Пулы кеша реализуются адаптерами кеша.

Простое приложение

Давайте создадим простое приложение, чтобы понять концепцию кеша.

Шаг 1 — Создайте новое приложение, пример кеша .

cd /path/to/app 
mkdir cache-example 
cd cache-example

Шаг 2 — Установите компонент кеша.

composer require symfony/cache

Шаг 3 — Создайте адаптер файловой системы.

require __DIR__ . '/vendor/autoload.php';  
use Symfony\Component\Cache\Adapter\FilesystemAdapter;  
$cache = new FilesystemAdapter(); 

Шаг 4 — Создайте элемент кэша, используя getItem и установите метод адаптера. getItem извлекает элемент кэша, используя его ключ. если ключ не присутствует, он создает новый элемент. Метод set хранит фактические данные.

$usercache = $cache->getitem('item.users'); 
$usercache->set(['jon', 'peter']); 
$cache->save($usercache); 

Шаг 5 — Получите доступ к элементу кэша, используя getItem, isHit и метод get . isHit информирует о доступности элемента кэша, а метод get предоставляет фактические данные.

$userCache = $cache->getItem('item.users'); 
if(!$userCache->isHit()) { 
   echo "item.users is not available"; 
} else { 
   $users = $userCache->get(); 
   var_dump($users); 
} 

Шаг 6 — Удалить элемент кэша, используя метод deleteItem .

$cache->deleteItem('item.users');

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

<?php  
   require __DIR__ . '/vendor/autoload.php'; 
   use Symfony\Component\Cache\Adapter\FilesystemAdapter;  

   $cache = new FilesystemAdapter();  
   $usercache = $cache->getitem('item.users'); 
   $usercache->set(['jon', 'peter']); 
   $cache->save($usercache);  
   $userCache = $cache->getItem('item.users'); 
   
   if(!$userCache->isHit()) { 
      echo "item.users is not available"; 
   } else { 
      $users = $userCache->get(); 
      var_dump($users); 
   }  
   $cache->deleteItem('item.users');  
?> 

Результат

array(2) { 
   [0]=> 
   string(3) "jon" 
   [1]=> 
   string(5) "peter" 
} 

отлаживать

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

use Symfony\Component\Debug\Debug  
Debug::enable()

Symfony предоставляет два класса, ErrorHandler и ExceptionHandler для отладки. В то время как ErrorHandler ловит ошибки PHP и преобразует их в исключения, ErrorException или FatalErrorException, ExceptionHandler перехватывает необработанные исключения PHP и преобразует их в полезный ответ PHP. ErrorHandler и ExceptionHandler по умолчанию отключены. Мы можем включить его с помощью метода register.

use Symfony\Component\Debug\ErrorHandler; 
use Symfony\Component\Debug\ExceptionHandler;  
ErrorHandler::register(); 
ExceptionHandler::register(); 

В веб-приложении Symfony среда отладки предоставляется DebugBundle. Зарегистрируйте пакет в методе registerBundles AppKernel, чтобы включить его.

if (in_array($this->getEnvironment(), ['dev', 'test'], true)) { 
   $bundles[] = new Symfony\Bundle\DebugBundle\DebugBundle(); 
}

Profiler

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

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

if (in_array($this->getEnvironment(), ['dev', 'test'], true)) { 
   $bundles[] = new Symfony\Bundle\WebProfilerBundle\WebProfilerBundle(); 
}

Компонент веб-профиля можно настроить в разделе web_profile файла конфигурации приложения , app / config / config.xml.

web_profiler: 
   toolbar:      false 
   position:     bottom 

Приложение Symfony показывает профилированные данные в нижней части страницы в виде отдельного раздела.

Приложение Symfony

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

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

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

  • symfony / security-core — базовая функциональность безопасности.
  • symfony / security-http — встроенная функция безопасности в протоколе HTTP.
  • symfony / security-csrf — защита от подделки межсайтовых запросов в веб-приложении.
  • symfony / security-acl — расширенная структура безопасности на основе списка контроля доступа.

Простая аутентификация и авторизация

Давайте изучим концепцию аутентификации и авторизации с помощью простого демонстрационного приложения.

Шаг 1. Создайте новую демонстрацию безопасности веб-приложения с помощью следующей команды.

 symfony new securitydemo

Шаг 2 — Включите функцию безопасности в приложении, используя файл конфигурации безопасности. Конфигурация, связанная с безопасностью, находится в отдельном файле security.yml . Конфигурация по умолчанию следующая.

security: 
   providers: 
      in_memory: 
         memory: ~ 
   firewalls: 
      dev: 
         pattern: ^/(_(profiler|wdt)|css|images|js)/ 
         security: false  
   main: 
      anonymous: ~ 
      #http_basic: ~ 
      #form_login: ~

Конфигурация по умолчанию обеспечивает основанный на памяти провайдер безопасности и анонимный доступ ко всем страницам. Раздел брандмауэра исключает файлы, соответствующие шаблону, ^ / (_ (profiler | wdt) | css | images | js) / из структуры безопасности. Шаблон по умолчанию включает таблицы стилей, изображения и скрипты Java (а также инструменты разработки, такие как профилировщик).

Шаг 3 — Включите проверку подлинности системы на основе HTTP, добавив параметр http_basic в основной раздел следующим образом.

security: 
   # ...  
   firewalls: 
      # ...  
      main: 
         anonymous: ~ 
         http_basic: ~ 
         #form_login: ~ 

Шаг 4 — Добавьте некоторых пользователей в раздел провайдера памяти. Также добавьте роли для пользователей.

security: 
   providers: 
      in_memory: 
         memory: 
            users: 
               myuser: 
                  password: user 
                  roles: 'ROLE_USER' 
                     myadmin: 
                        password: admin 
                        roles: 'ROLE_ADMIN' 

Мы добавили двух пользователей: пользователя в роли ROLE_USER и администратора в роли ROLE_ADMIN.

Шаг 5 — Добавьте кодировщик, чтобы получить полную информацию о текущем вошедшем в систему пользователе. Целью кодировщика является получение полной информации о текущем пользовательском объекте из веб-запроса.

security: 
   # ... 
   encoders: 
      Symfony\Component\Security\Core\User\User: bcrypt 
      # ...  

Symfony предоставляет интерфейс UserInterface для получения таких сведений о пользователе, как имя пользователя, роли, пароль и т. Д. Нам необходимо реализовать интерфейс в соответствии с нашими требованиями и настроить его в разделе кодировщика.

Например, давайте рассмотрим, что пользовательские данные находятся в базе данных. Затем нам нужно создать новый класс User и реализовать методы UserInterface для получения сведений о пользователе из базы данных. Как только данные доступны, система безопасности использует их, чтобы разрешить / запретить пользователю. Symfony предоставляет реализацию User по умолчанию для провайдера памяти. Алгоритм используется для расшифровки пароля пользователя.

Шаг 6 — Зашифруйте пароль пользователя с помощью алгоритма bcrypt и поместите его в файл конфигурации. Поскольку мы использовали алгоритм bcrypt , объект User пытается расшифровать пароль, указанный в файле конфигурации, а затем пытается сопоставить его с паролем, введенным пользователем. Консольное приложение Symfony предоставляет простую команду для шифрования пароля.

php bin/console security:encode-password admin 
Symfony Password Encoder Utility 
================================  
------------------ -----------------------------------
Key   Value  
------------------ ------------------------------------
Encoder used       Symfony\Component\Security\Core\Encoder\BCryptPasswordEncoder         
Encoded password   
$2y$12$0Hy6/.MNxWdFcCRDdstHU.hT5j3Mg1tqBunMLIUYkz6..IucpaPNO    
------------------ ------------------------------------   
! [NOTE] Bcrypt encoder used: the encoder generated its own built-in salt.
[OK] Password encoding succeeded 

Шаг 7 — Используйте команду для генерации зашифрованного пароля и обновления его в файле конфигурации.

# To get started with security, check out the documentation: 
# http://symfony.com/doc/current/security.html 
   security:  
      # http://symfony.com/doc/current/security.html#b-configuring-how-users-are-loaded 
      providers: 
         in_memory: 
            memory: 
               users: 
                  user: 
                     password: $2y$13$WsGWNufreEnVK1InBXL2cO/U7WftvfNvH
                     Vb/IJBH6JiYoDwVN4zoi  
                     roles: 'ROLE_USER' 
                     admin: 
                        password: $2y$13$jQNdIeoNV1BKVbpnBuhKRuOL01NeMK
                        F7nEqEi/Mqlzgts0njK3toy  
                        roles: 'ROLE_ADMIN' 
                         
         encoders: 
            Symfony\Component\Security\Core\User\User: bcrypt  
         firewalls: 
            # disables authentication for assets and the profiler, 
            # adapt it according to your needs 
         dev: 
            pattern: ^/(_(profiler|wdt)|css|images|js)/
         security: false  
         main: 
            anonymous: ~ 
            # activate different ways to authenticate  
            # http://symfony.com/doc/current/security.html#a-co
            nfiguring-howyour-users-will-authenticate 
            http_basic: ~  
            # http://symfony.com/doc/current/cookbook/security/
            form_login_setup.html 
            #form_login: ~             

Шаг 8 — Теперь примените безопасность к некоторому разделу приложения. Например, ограничьте раздел администратора пользователями в роли ROLE_ADMIN.

security: 
   # ... 
      firewalls: 
         # ... 
      default: 
         # ...  
      access_control: 
         # require ROLE_ADMIN for /admin* 
         - { path: ^/admin, roles: 'ROLE_ADMIN' } 

Шаг 9 — Добавьте страницу администратора в DefaultController следующим образом.

/** 
   * @Route("/admin") 
*/ 
public function adminLandingAction() { 
   return new Response('<html><body>This is admin section.</body></html>'); 
} 

Шаг 10 — Наконец, зайдите на страницу администратора, чтобы проверить настройки безопасности в браузере. Браузер запросит имя пользователя и пароль и разрешит доступ только настроенным пользователям.

Результат

соединительный

Раздел администратора

Workflow

Рабочий процесс — это продвинутая концепция, которая используется во многих корпоративных приложениях. В приложении электронной коммерции процесс доставки продукта представляет собой рабочий процесс. Продукт сначала оплачивается (создание заказа), закупается в магазине и упаковывается (упаковка / готова к отправке) и отправляется пользователю. Если есть какие-либо проблемы, продукт возвращается от пользователя, и заказ отменяется. Порядок потока действий очень важен. Например, мы не можем доставить товар без выставления счетов.

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

Давайте разберемся с концепцией рабочего процесса, создав простое приложение для управления отпусками.

Шаг 1 — Создайте новое приложение, пример рабочего процесса .

cd /path/to/dev 
mkdir workflow-example 

cd workflow-example 
composer require symfony/workflow

Шаг 2 — Создайте новый класс, оставьте атрибуты apply_by, left_on и status .

class Leave { 
   public $applied_by; 
   public $leave_on;  
   public $status; 
} 

Здесь «application_by» относится к сотрудникам, которые хотят уйти. Оставить_он относится к дате отпуска. статус относится к статусу отпуска.

Шаг 3 — Управление отпуском имеет четыре места: применено, in_process и одобрено / отклонено.

use Symfony\Component\Workflow\DefinitionBuilder; 
use Symfony\Component\Workflow\Transition; 
use Symfony\Component\Workflow\Workflow; 
use Symfony\Component\Workflow\MarkingStore\SingleStateMarkingStore; 
use Symfony\Component\Workflow\Registry; 
use Symfony\Component\Workflow\Dumper\GraphvizDumper;

$builder = new DefinitionBuilder(); 
$builder->addPlaces(['applied', 'in_process', 'approved', 'rejected']);  

Здесь мы создали новое определение с использованием DefinitionBuilder и добавили места с помощью метода addPlaces .

Шаг 4 — Определите действия, необходимые для перемещения из одного места в другое.

$builder->addTransition(new Transition('to_process', 'applied', 'in_process')); 
$builder->addTransition(new Transition('approve', 'in_process', 'approved')); 
$builder->addTransition(new Transition('reject', 'in_process', 'rejected')); 

Здесь у нас есть три перехода, to_process, одобрить и отклонить . Переход to_process принимает приложение выхода и перемещает место из примененного в in_process. Одобрить переход одобряет заявление на отпуск и перемещает место в утвержденный. Аналогично, отклонение перехода отклоняет заявку на отпуск и перемещает место в отклоненное. Мы создали все переходы, используя метод addTransition.

Шаг 5 — Постройте определение, используя метод сборки.

$definition = $builder->build();

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

$dumper = new GraphvizDumper(); 
echo $dumper->dump($definition);

Графвиз Дот Формат

Шаг 7 — Создайте разметку магазина, в которой будут храниться текущие места / статус объекта.

$marking = new SingleStateMarkingStore('status');

Здесь мы использовали класс SingleStateMarkingStore для создания метки, и он помечает текущий статус в свойстве status объекта. В нашем примере объектом является объект Leave.

Шаг 8 — Создайте рабочий процесс, используя определение и маркировку.

$leaveWorkflow =    new Workflow($definition, $marking);

Здесь мы использовали класс Workflow для создания рабочего процесса.

Шаг 9 — Добавьте рабочий процесс в реестр инфраструктуры рабочего процесса, используя класс Registry .

$registry = new Registry(); 
$registry->add($leaveWorkflow, Leave::class);

Шаг 10 — Наконец, используйте рабочий процесс, чтобы определить, применяется ли данный переход с помощью метода can, и, если это так, примените переход с помощью метода apply. Когда применяется переход, статус объекта перемещается из одного места в другое.

$workflow = $registry->get($leave); 
echo "Can we approve the leave now? " . $workflow->can($leave, 'approve') . "\r\n"; 
echo "Can we approve the start process now? " . $workflow->can($leave, 'to_process') . "\r\n"; 

$workflow->apply($leave, 'to_process'); 
echo "Can we approve the leave now? " . $workflow->can($leave, 'approve') . "\r\n"; 
echo $leave->status . "\r\n"; 

$workflow->apply($leave, 'approve'); 
echo $leave->status . "\r\n";

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