Компонент "Рабочий поток" (Workflow)
Компонент "Рабочий поток" предоставляет инструменты для управления рабочим процессом или конечным автоматом.
Компонент "Рабочий поток" был добавлен в версии 3.2
Установка
Компонент можно установить двумя способами:
- Используя Composer
- Используя официальный Git репозиторий (https://github.com/symfony/workflow)
После необходимо включить файл vendor/autoload.php
для использования механизма автозагрузки Composer'а. Иначе приложение не сможет найти классы данного компонента.
Создание Workflow
Компонент "Рабочий поток" предоставляет объектно-ориентированный способ определения процесса или жизненного цикла через который проходит объект. Также необходимо определить переходы (transitions), каждый из которых описывает действие которое необходимо сделать чтобы попасть из одного места (place) в другое.
Примечание переводчика: здесь почему-то на картинке упоминается слово transaction, а не transition
Набор мест и переходов образует определение (Definition). Рабочему потоку требуется экземпляр Definition и метод описания состояний объектов (т.е. экземпляр MarkingStoreInterface).
Рассмотрим пример публикации в блоге. Публикация может иметь один из предопределенных статусов (черновик, на проверке, отклонена, опубликована). В рамках рабочего потока эти статусы называются местами.
Вы можете определить рабочий поток так:
use Symfony\Component\Workflow\DefinitionBuilder;
use Symfony\Component\Workflow\Transition;
use Symfony\Component\Workflow\Workflow;
use Symfony\Component\Workflow\MarkingStore\SingleStateMarkingStore;
$builder = new DefinitionBuilder();
$builder->addPlaces(['draft', 'review', 'rejected', 'published']);
// Transitions are defined with a unique name, an origin place and a destination place
$builder->addTransition(new Transition('to_review', 'draft', 'review'));
$builder->addTransition(new Transition('publish', 'review', 'published'));
$builder->addTransition(new Transition('reject', 'review', 'rejected'));
$definition = $builder->build();
$marking = new SingleStateMarkingStore('currentState');
$workflow = new Workflow($definition, $marking);
Workflow поможет нам определить какие действия доступны для публикации в зависимости от места в котором она находится. Тем самым сохранив логику предметной области в одном месте и не размазывая ее по всему приложению.
При определении нескольких рабочих потоков стоит подумать об использовании реестра (Registry), в качестве объекта хранящего и предоставляющего доступ к различным рабочим потокам.
Реестр также помогает определить какой объект поддерживается рабочим потоком при попытке его использовать:
use Symfony\Component\Workflow\Registry;
use Acme\Entity\BlogPost;
use Acme\Entity\Newsletter;
$blogWorkflow = ...
$newsletterWorkflow = ...
$registry = new Registry();
$registry->add($blogWorkflow, BlogPost::class);
$registry->add($newsletterWorkflow, Newsletter::class);
Использование
// ...
$post = new BlogPost();
$workflow = $registry->get($post);
$workflow->can($post, 'publish'); // False
$workflow->can($post, 'to_review'); // True
$workflow->apply($post, 'to_review');
$workflow->can($post, 'publish'); // True
$workflow->getEnabledTransitions($post); // ['publish', 'reject']