July 21, 2016 Javier Eguiluz

Workflows are a fundamental element in lots of organizations' structures. They describe a sequence of operations that can be executed repeatedly to provide some service (e.g. buying a product in an e-commerce application), process some information (e.g. publishing some content in a CMS application), etc.

In Symfony 3.2 we added a new Workflow component to help you define those workflows in your applications. Technically, the component implements a "workflow net", which is a subclass of the Petri net.

In practice, to create a workflow you define "states" and "transitions" (which are the events that may occur between two states). The following example shows a minimal workflow to publish some content:

1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 framework : workflows : article_publishing : marking_store : type : property_accessor supports : - AppBundle\Entity\Article places : - draft - spellchecked - published transitions : spellcheck : from : draft to : spellchecked publish : from : spellchecked to : published

Now you can start using this workflow in your templates and controllers. For example, in a template:

1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 {# the workflow name is optional when there is just one workflow for the class #} {% if workflow_can ( article , 'publish' ) %} <a href="...">Publish article</a> {% endif %} {# if more than one workflow is defined for the 'Article' class #} {% if workflow_can ( article , 'publish' , 'article_publishing' ) %} <a href="...">Publish article</a> {% endif %} {# ... #} {% for transition in workflow_transitions ( article ) %} <a href="..."> {{ transition.name }} </a> {% else %} No actions available for this article. {% endfor %}

In a controller, you can get any defined workflow by its name thanks to the workflow registry created by Symfony and then, apply any given transition to it:

1 2 3 4 5 6 7 8 9 10 11 use Symfony\Component\Workflow\Exception\LogicException ; public function reviewAction ( Article $article ) { // the try/catch is needed because this transition could already have been applied try { $this -> get ( 'workflow.article_publishing' ) -> apply ( $article , 'spellcheck' ); } catch ( LogicException $e ) { // ... } }

If you want to execute custom logic when a transition happens, you can hook listeners to the events triggered by the component.

Check out this demo application for a full example of the workflow component in action and check out this GitHub project for an unofficial port of the component for Symfony 2.3+ versions.