Share
Embed
Business-Workflows in Symfony-Anwendungen modellieren
SymfonyLive Cologone 2017
Christian Flothmann
April 07, 2017
Transcript
36 slides
-
Christian Flothmann Symfony Core Team & Documentation Team Entwickler bei
SensioLabs Deutschland github.com/xabbuh @xabbuh -
• eingeführt in Symfony 3.2 • unterstützt Workflow Nets und
State Machines • in Twig und das Full-Stack Framework integriert • Audit Logging Die Workflow Komponente -
• Subject: Objekt, auf das ein Workflow angewandt wird •
Place: Zustände, die ein Workflow annehmen kann • Transition: (benannter) Übergang zwischen zwei Places Terminologie -
• Marking: Zustand/Zustände, in denen sich ein Workflow befindet •
Marking Store: Mapping des Workflow Markings auf Properties des Subjects Terminologie -
AppBundle\Entity\Order class Order { /** * @var string */ private
$state; /** * @var Customer */ private $customer; /** * @var Product[] */ private $products; } -
Konfiguration framework: # ... workflows: order_payment: marking_store: type: single_state arguments:
[state] supports: - AppBundle\Entity\Order # ... -
Konfiguration framework: workflows: order_payment: places: - placed - paid -
payment_failed - delivered - returned - refunded initial_place: placed -
Konfiguration framework: workflows: order_payment: transitions: pay: from: [placed, payment_failed] to:
paid deliver: from: paid to: delivered # ... -
Verwendung des Workflows public function startDeliveryAction(Order $order) { $workflow =
$this->get('workflow.order_payment'); if (!$workflow->can($order, 'deliver')) { // Error Handling } $workflow->apply($order, 'deliver'); // ... } -
Twig-Integration {# Transition auf Anwendbarkeit testen #} {% if workflow_can(order,
'deliver', 'order_payment') %} <a href="{{ path('deliver_order') }}">Deliver</a> {% endif %} {# alle anwendbaren Transitionen #} {% for t in workflow_transitions(order, 'order_payment') %} <a href="{{ path(t.name ~ '_order') }}"> {{ ('transition.' ~ t.name)|trans }} </a> {% endfor %} -
• workflow.leave vor dem Verlassen eines Places • workflow.transition vor
dem Anwenden einer Transition • workflow.enter vor dem Entern eines Places • workflow.<workflow>.announce.<transition> Announcement aktivierter Transitions Event-Kategorien -
Die Event Klasse use Symfony\Component\EventDispatcher\Event as BaseEvent; class Event extends
BaseEvent { // ... public function getMarking() { return $this->marking; } public function getSubject() { return $this->subject; } public function getTransition() { return $this->transition; } } -
Beispiel: Audit Logging services: audit_trail_logger: class: Symfony\Component\Workflow\EventListener\AuditTrailListener arguments: ['@logger'] tags:
- name: kernel.event_subscriber event: workflow.order_payment.leave method: onLeave - name: kernel.event_listener event: workflow.order_payment.transition method: onTransition - name: kernel.event_listener event: workflow.order_payment.enter method: onEnter -
• Möglichkeit durch Event Listener Ausführung von Transitionen zu blocken
• Events: o workflow.guard o workflow.<workflow>.guard o workflow.<workflow>.guard.<transition> Guard Events -
Beispiel: rollenbasierter Access Check class RoleGuardListener { private $authorizationChecker; public
function __construct( AuthorizationCheckerInterface $authorizationChecker ) { $this->authorizationChecker = $authorizationChecker; } public function canDeliver(GuardEvent $event) { if (!$this->authorizationChecker->isGranted('ROLE_DELIVERER')) { $event->setBlocked(true); } } } -
Beispiel: rollenbasierter Access Check services: role_guard_listener: class: AppBundle\Workflow\RoleGuardListener arguments: ['@security.authorization_checker']
tags: - name: kernel.event_listener event: workflow.order_payment.guard.deliver method: canDeliver -
Neue Twig-Funktionen {# prüfen, ob ein Workflow in einem gewünschten
Place ist #} {% if workflow_has_marked_place(order, 'paid', 'order_payment') %} bezahlt {% endif %} {# aktive Places ermitteln #} {{ workflow_marked_places(order, true, 'order_payment')|join(', ') }} -
• neues Event: workflow.entered • nachdem ein Place aktiviert wurde
• Abstufungen: o workflow.entered o workflow.<workflow>.entered o workflow. <workflow>.entered.<place> • neue Methode: getWorkflowName() Änderungen am Event-System -
Guard Expression Support framework: workflows: order_payment: # ... transitions: deliver:
guard: 'has_role("ROLE_DELIVERER")' from: paid to: delivered # ... -
• subject • token • user • roles Guard Expression
Support, Variablen -
• is_granted() • is_anonymous() • is_authenticated() • is_fully_authenticated() • is_rememberme()
• has_role() Guard Expression Support, Funktionen -
Symfony 3.2 services: audit_trail_logger: class: Symfony\Component\Workflow\EventListener\AuditTrailListener arguments: ['@logger'] tags: -
name: kernel.event_subscriber event: workflow.order_payment.leave method: onLeave - name: kernel.event_listener event: workflow.order_payment.transition method: onTransition - name: kernel.event_listener event: workflow.order_payment.enter method: onEnter -
Benutzerdefinierte Support Strategien use Symfony\Component\Workflow\SupportStrategy\SupportStrategyInterface; class EconomySupportStrategy implements SupportStrategyInterface {
public function supports(Workflow $workflow, $subject) { if (!$subject instanceof Article) { return false; } return $subject->getCategory() === Article::CATEGORY_ECONOMY; } }