Skip to content
  • About
    • What is Symfony?
    • Community
    • News
    • Contributing
    • Support
  • Documentation
    • Symfony Docs
    • Symfony Book
    • Screencasts
    • Symfony Bundles
    • Symfony Cloud
    • Training
  • Services
    • Platform.sh for Symfony Best platform to deploy Symfony apps
    • SymfonyInsight Automatic quality checks for your apps
    • Symfony Certification Prove your knowledge and boost your career
    • SensioLabs Professional services to help you with Symfony
    • Blackfire Profile and monitor performance of your apps
  • Other
  • Blog
  • Download
sponsored by SensioLabs
  1. Home
  2. Documentation
  3. Workflow
  4. How to Dump Workflows
  • Documentation
  • Book
  • Reference
  • Bundles
  • Cloud
  • 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).

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.

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): void {
    // ...
    $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.
TOC
    Version
    We stand with Ukraine.
    Version:

    Symfony 6.3 is backed by

    Symfony 6.3 is backed by

    Symfony 6.3 is backed by

    Symfony 6.3 is backed by

    The life jacket for your team and your project

    The life jacket for your team and your project

    Symfony Code Performance Profiling

    Symfony Code Performance Profiling

    Symfony footer

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

    Avatar of Damon Jones, a Symfony contributor

    Thanks Damon Jones (@damon__jones) for being a Symfony contributor

    1 commit • 2 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 Meilisearch