Symfony
sponsored by SensioLabs
Menu
  • About
  • Documentation
  • Screencasts
  • Cloud
  • Certification
  • Community
  • Businesses
  • News
  • Download
  1. Home
  2. Documentation
  3. Workflow
  4. How to Dump Workflows
  • Documentation
  • Book
  • Reference
  • Bundles
  • Cloud
Search by Algolia
  • Styling

How to Dump Workflows

Edit this page

How to Dump Workflows

To help you debug your workflows, you can generate a visual representation of them as SVG or PNG images. First, install any of these free and open source applications needed to generate the images:

  • Graphviz, provides the dot command;
  • Mermaid CLI, provides the mmdc command;
  • PlantUML, provides the plantuml.jar file (which requires Java).

5.3

The mermaid dump format was introduced in Symfony 5.3.

If you are defining the workflow inside a Symfony application, run this command to dump it as an image:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
# using Graphviz's 'dot' and SVG images
$ php bin/console workflow:dump workflow-name | dot -Tsvg -o graph.svg

# using Graphviz's 'dot' and PNG images
$ php bin/console workflow:dump workflow-name | dot -Tpng -o graph.png

# using PlantUML's 'plantuml.jar'
$ php bin/console workflow:dump workflow_name --dump-format=puml | java -jar plantuml.jar -p  > graph.png

# highlight 'place1' and 'place2' in the dumped workflow
$ php bin/console workflow:dump workflow-name place1 place2 | dot -Tsvg -o graph.svg

# using Mermaid.js CLI
$ php bin/console workflow:dump workflow_name --dump-format=mermaid | mmdc -o graph.svg

The DOT image will look like this:

The Mermaid image will look like this:

The PlantUML image will look like this:

If you are creating workflows outside of a Symfony application, use the GraphvizDumper or StateMachineGraphvizDumper class to create the DOT files and PlantUmlDumper to create the PlantUML files:

1
2
3
4
5
6
7
// Add this code to a PHP script; for example: dump-graph.php
$dumper = new GraphvizDumper();
echo $dumper->dump($definition);

# if you prefer PlantUML, use this code:
# $dumper = new PlantUmlDumper();
# echo $dumper->dump($definition);
1
2
3
# replace 'dump-graph.php' by the name of your PHP script
$ php dump-graph.php | dot -Tsvg -o graph.svg
$ php dump-graph.php | java -jar plantuml.jar -p  > graph.png

Styling

You can use metadata with the following keys to style the workflow:

  • for places:

    • bg_color: a color;
    • description: a string that describes the state.
  • for transitions:

    • label: a string that replaces the name of the transition;
    • color: a color;
    • arrow_color: a color.

Strings can include \n characters to display the contents in multiple lines. Colors can be defined as:

  • a color name from PlantUML's color list;
  • an hexadecimal color (both #AABBCC and #ABC formats are supported).

Note

The Mermaid dumper does not support coloring the arrow heads with arrow_color as there is no support in Mermaid for doing so.

Below is the configuration for the pull request state machine with styling added.

  • YAML
  • XML
  • PHP
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
# config/packages/workflow.yaml
framework:
    workflows:
        pull_request:
            type: 'state_machine'
            marking_store:
                type: 'method'
                property: 'currentPlace'
            supports:
                - App\Entity\PullRequest
            initial_marking: start
            places:
                start: ~
                coding: ~
                test: ~
                review:
                    metadata:
                        description: Human review
                merged: ~
                closed:
                    metadata:
                        bg_color: DeepSkyBlue
            transitions:
                submit:
                    from: start
                    to: test
                update:
                    from: [coding, test, review]
                    to: test
                    metadata:
                        arrow_color: Turquoise
                wait_for_review:
                    from: test
                    to: review
                    metadata:
                        color: Orange
                request_change:
                    from: review
                    to: coding
                accept:
                    from: review
                    to: merged
                    metadata:
                        label: Accept PR
                reject:
                    from: review
                    to: closed
                reopen:
                    from: closed
                    to: review
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
<!-- config/packages/workflow.xml -->
<?xml version="1.0" encoding="UTF-8" ?>
<container xmlns="http://symfony.com/schema/dic/services"
    xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
    xmlns:framework="http://symfony.com/schema/dic/symfony"
    xsi:schemaLocation="http://symfony.com/schema/dic/services https://symfony.com/schema/dic/services/services-1.0.xsd
        http://symfony.com/schema/dic/symfony https://symfony.com/schema/dic/symfony/symfony-1.0.xsd"
>

    <framework:config>
        <framework:workflow name="pull_request" type="state_machine">
            <framework:marking-store>
                <framework:type>method</framework:type>
                <framework:property>currentPlace</framework:property>
            </framework:marking-store>

            <framework:support>App\Entity\PullRequest</framework:support>

            <framework:initial_marking>start</framework:initial_marking>

            <framework:place>start</framework:place>
            <framework:place>coding</framework:place>
            <framework:place>test</framework:place>
            <framework:place name="review">
                <framework:metadata>
                    <framework:description>Human review</framework:description>
                </framework:metadata>
            </framework:place>
            <framework:place>merged</framework:place>
            <framework:place name="closed">
                <framework:metadata>
                    <framework:bg_color>DeepSkyBlue</framework:bg_color>
                </framework:metadata>
            </framework:place>

            <framework:transition name="submit">
                <framework:from>start</framework:from>

                <framework:to>test</framework:to>
            </framework:transition>

            <framework:transition name="update">
                <framework:from>coding</framework:from>
                <framework:from>test</framework:from>
                <framework:from>review</framework:from>

                <framework:to>test</framework:to>

                <framework:metadata>
                    <framework:arrow_color>Turquoise</framework:arrow_color>
                </framework:metadata>
            </framework:transition>

            <framework:transition name="wait_for_review">
                <framework:from>test</framework:from>

                <framework:to>review</framework:to>

                <framework:metadata>
                    <framework:color>Orange</framework:color>
                </framework:metadata>
            </framework:transition>

            <framework:transition name="request_change">
                <framework:from>review</framework:from>

                <framework:to>coding</framework:to>
            </framework:transition>

            <framework:transition name="accept">
                <framework:from>review</framework:from>

                <framework:to>merged</framework:to>

                <framework:metadata>
                    <framework:label>Accept PR</framework:label>
                </framework:metadata>
            </framework:transition>

            <framework:transition name="reject">
                <framework:from>review</framework:from>

                <framework:to>closed</framework:to>
            </framework:transition>

            <framework:transition name="reopen">
                <framework:from>closed</framework:from>

                <framework:to>review</framework:to>
            </framework:transition>

        </framework:workflow>

    </framework:config>
</container>
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
// config/packages/workflow.php
use Symfony\Config\FrameworkConfig;

return static function (FrameworkConfig $framework) {
    // ...
    $pullRequest = $framework->workflows()->workflows('pull_request');

    $pullRequest
        ->type('state_machine')
        ->supports(['App\Entity\PullRequest'])
        ->initialMarking(['start']);

    $pullRequest->markingStore()
        ->type('method')
        ->property('currentPlace');

    $pullRequest->place()->name('start');
    $pullRequest->place()->name('coding');
    $pullRequest->place()->name('test');
    $pullRequest->place()
        ->name('review')
        ->metadata(['description' => 'Human review']);
    $pullRequest->place()->name('merged');
    $pullRequest->place()
        ->name('closed')
        ->metadata(['bg_color' => 'DeepSkyBlue',]);

    $pullRequest->transition()
        ->name('submit')
            ->from(['start'])
            ->to(['test']);

    $pullRequest->transition()
        ->name('update')
            ->from(['coding', 'test', 'review'])
            ->to(['test'])
            ->metadata(['arrow_color' => 'Turquoise']);

    $pullRequest->transition()
        ->name('wait_for_review')
            ->from(['test'])
            ->to(['review'])
            ->metadata(['color' => 'Orange']);

    $pullRequest->transition()
        ->name('request_change')
            ->from(['review'])
            ->to(['coding']);

    $pullRequest->transition()
        ->name('accept')
            ->from(['review'])
            ->to(['merged'])
            ->metadata(['label' => 'Accept PR']);

    $pullRequest->transition()
        ->name('reject')
            ->from(['review'])
            ->to(['closed']);

    $pullRequest->transition()
        ->name('accept')
            ->from(['closed'])
            ->to(['review']);
};

The PlantUML image will look like this:

This work, including the code samples, is licensed under a Creative Commons BY-SA 3.0 license.
We stand with Ukraine.
Version:

Symfony 5.4 is backed by

Symfony Code Performance Profiling

Symfony Code Performance Profiling

Check Code Performance in Dev, Test, Staging & Production

Check Code Performance in Dev, Test, Staging & Production

↓ Our footer now uses the colors of the Ukrainian flag because Symfony stands with the people of Ukraine.

Avatar of Kris Buist, a Symfony contributor

Thanks Kris Buist for being a Symfony contributor

1 commit • 10 lines changed

View all contributors that help us make Symfony

Become a Symfony contributor

Be an active part of the community and contribute ideas, code and bug fixes. Both experts and newcomers are welcome.

Learn how to contribute

Symfony™ is a trademark of Symfony SAS. All rights reserved.

  • What is Symfony?
    • Symfony at a Glance
    • Symfony Components
    • Case Studies
    • Symfony Releases
    • Security Policy
    • Logo & Screenshots
    • Trademark & Licenses
    • symfony1 Legacy
  • Learn Symfony
    • Symfony Docs
    • Symfony Book
    • Reference
    • Bundles
    • Best Practices
    • Training
    • eLearning Platform
    • Certification
  • Screencasts
    • Learn Symfony
    • Learn PHP
    • Learn JavaScript
    • Learn Drupal
    • Learn RESTful APIs
  • Community
    • SymfonyConnect
    • Support
    • How to be Involved
    • Code of Conduct
    • Events & Meetups
    • Projects using Symfony
    • Downloads Stats
    • Contributors
    • Backers
  • Blog
    • Events & Meetups
    • A week of symfony
    • Case studies
    • Cloud
    • Community
    • Conferences
    • Diversity
    • Documentation
    • Living on the edge
    • Releases
    • Security Advisories
    • SymfonyInsight
    • Twig
    • SensioLabs
  • Services
    • SensioLabs services
    • Train developers
    • Manage your project quality
    • Improve your project performance
    • Host Symfony projects
    Deployed on
Follow Symfony
Search by Algolia