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.
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
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