Slide 1

Slide 1 text

SensioLabs Business-Workflows in Symfony- Anwendungen modellieren

Slide 2

Slide 2 text

Christian Flothmann Symfony Core Team & Documentation Team Entwickler bei SensioLabs Deutschland github.com/xabbuh @xabbuh

Slide 3

Slide 3 text

Die Workflow Komponente

Slide 4

Slide 4 text

• 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

Slide 5

Slide 5 text

• Subject: Objekt, auf das ein Workflow angewandt wird • Place: Zustände, die ein Workflow annehmen kann • Transition: (benannter) Übergang zwischen zwei Places Terminologie

Slide 6

Slide 6 text

• Marking: Zustand/Zustände, in denen sich ein Workflow befindet • Marking Store: Mapping des Workflow Markings auf Properties des Subjects Terminologie

Slide 7

Slide 7 text

Beispiel: Bestellungen in einem Onlineshop

Slide 8

Slide 8 text

AppBundle\Entity\Order class Order { /** * @var string */ private $state; /** * @var Customer */ private $customer; /** * @var Product[] */ private $products; }

Slide 9

Slide 9 text

Konfiguration framework: # ... workflows: order_payment: marking_store: type: single_state arguments: [state] supports: - AppBundle\Entity\Order # ...

Slide 10

Slide 10 text

Konfiguration framework: workflows: order_payment: places: - placed - paid - payment_failed - delivered - returned - refunded initial_place: placed

Slide 11

Slide 11 text

Konfiguration framework: workflows: order_payment: transitions: pay: from: [placed, payment_failed] to: paid deliver: from: paid to: delivered # ...

Slide 12

Slide 12 text

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'); // ... }

Slide 13

Slide 13 text

Twig-Integration {# Transition auf Anwendbarkeit testen #} {% if workflow_can(order, 'deliver', 'order_payment') %} Deliver {% endif %} {# alle anwendbaren Transitionen #} {% for t in workflow_transitions(order, 'order_payment') %} {{ ('transition.' ~ t.name)|trans }} {% endfor %}

Slide 14

Slide 14 text

Das Event-System

Slide 15

Slide 15 text

• workflow.leave vor dem Verlassen eines Places • workflow.transition vor dem Anwenden einer Transition • workflow.enter vor dem Entern eines Places • workflow..announce. Announcement aktivierter Transitions Event-Kategorien

Slide 16

Slide 16 text

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; } }

Slide 17

Slide 17 text

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

Slide 18

Slide 18 text

• Möglichkeit durch Event Listener Ausführung von Transitionen zu blocken • Events: o workflow.guard o workflow..guard o workflow..guard. Guard Events

Slide 19

Slide 19 text

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); } } }

Slide 20

Slide 20 text

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

Slide 21

Slide 21 text

SensioLabs Neu in Symfony 3.3

Slide 22

Slide 22 text

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(', ') }}

Slide 23

Slide 23 text

• neues Event: workflow.entered • nachdem ein Place aktiviert wurde • Abstufungen: o workflow.entered o workflow..entered o workflow. .entered. • neue Methode: getWorkflowName() Änderungen am Event-System

Slide 24

Slide 24 text

Guard Expression Support

Slide 25

Slide 25 text

Guard Expression Support framework: workflows: order_payment: # ... transitions: deliver: guard: 'has_role("ROLE_DELIVERER")' from: paid to: delivered # ...

Slide 26

Slide 26 text

• subject • token • user • roles Guard Expression Support, Variablen

Slide 27

Slide 27 text

• is_granted() • is_anonymous() • is_authenticated() • is_fully_authenticated() • is_rememberme() • has_role() Guard Expression Support, Funktionen

Slide 28

Slide 28 text

Verbesserte Integration des AuditTrailLogger

Slide 29

Slide 29 text

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

Slide 30

Slide 30 text

Symfony 3.3 framework: workflows: order_payment: supports: AppBundle\Entity\Order audit_trail: true # ...

Slide 31

Slide 31 text

Benutzerdefinierte Support Strategien

Slide 32

Slide 32 text

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; } }

Slide 33

Slide 33 text

Benutzerdefinierte Support Strategien services: economy_article_strategy: class: AppBundle\EconomySupportStrategy

Slide 34

Slide 34 text

Benutzerdefinierte Support Strategien framework: workflows: economy_article_publication: support_strategy: economy_article_strategy # ...

Slide 35

Slide 35 text

SensioLabs Vielen Dank!

Slide 36

Slide 36 text

SensioLabs https://joind.in/talk/10c9f