New in Symfony 3.2: Workflow component

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.

Comments

This looks super useful for a lot of applications we develop. Can't wait to try this out in some upcoming project.

Also many thanks to fduch for creating a backported version. This might give me the change to use this on some older apps stuck at Symfony 2.7/2.8.
Great overview! And thanks for mention.
It seems like this component will tightly couple the business logic with the framework, which is something that goes against your best practices: http://symfony.com/doc/current/best_practices/business-logic.html
This one is preatty cool!
I was looking for such a solution from a long time!
In the code workflow_can(article, 'publish') how is determined the current state of the object article?
Have used it one week ago in production! Thanks for the component!
@Tito : I guess the state is registered in the object, and the object has an interface or something?
@Alex, I was wondering that, but I do not see any related interface in the base code. Is it up to the listeners to do the actual work of validating and changing state?
I could use this in some projects, but I don't see it as a core component.
So basically just a state machine...
There is a typo in the php code example in the service name:
$this->get('worflow.article_publishing')

It must be workflow, not worflow.
Are there ways to add validators to transitions or states so that a state or a transition can only be used when a certain condition is met?
The example from above does not work for me. I had to set the marking_store as well like in the example in https://github.com/lyrixx/SFLive-Paris2016-Workflow/blob/master/app/config/workflow.yml

Maybe you can add it above as well

marking_store:
type: property_accessor
Is the source code of the demo application available on github?
@Andrey thanks for the nice catch! It's fixed now.

@David fixed the missing "marking_store" config. Thanks!

@Tito the code of the demo app is at https://gith
ub.com/lyrixx/SFLive-Paris2016-Workflow/blob/master/app/config/workflow.yml
Is it possible to change a Wrkflow via an administration interface.
My question is to know if a certain user of the application with a specific role can see the workflow and add steps for example via an administration page.

Thanks

Comments are closed.

To ensure that comments stay relevant, they are closed for old posts.