362 words
2 minutes
Managing Workflows with Symfony 6

If you need to manage business processes (such as order management, leave requests, or publication workflows) in your Symfony application, the Workflow component can be very useful.


Using this component is relatively simple; we’ll proceed step by step:

  1. Create your entity (order, leave request, article, …)
  2. Configure the Workflow
  3. Use the Workflow

To use our workflow, we first need the Workflow component:

composer require symfony/workflow

Creating the Entity#

To create the entity, let’s model an order (for an online store). It will have two properties: an order number and a state, the latter being used for the workflow.

class Commande
{
    #[ORM\Id]
    #[ORM\GeneratedValue]
    #[ORM\Column]
    private ?int $id = null;

    #[ORM\Column]
    private ?int $numeroCommande = null;

    #[ORM\Column(length: 255)]
    private ?string $etatCommande = null;
}

Configuring the Workflow#

Here is the configuration of our workflow in the workflow.yaml file:

# config/packages/workflow.yaml

framework:
    workflows:
        commande:
            type: state_machine
            marking_store:
                type: 'method'
                property: 'etatCommande'
            supports:
                - App\Entity\Commande
            initial_marking: brouillon
            places:
                - brouillon
                - finalisee
                - rejetee
                - payee
            transitions:
                creation:
                    from: brouillon
                    to: finalisee
                rejet:
                    from: finalisee
                    to: rejetee
                payee:
                    from: finalisee
                    to: payee

Explanation:#

  • commande: Name of the workflow, used for dependency injection.
  • marking_store: Reference to the entity property storing the state (etatCommande).
  • supports: The entity concerned (Commande in our example).
  • initial_marking: Initial state of the entity (brouillon).
  • places: List of possible states for the entity (brouillon, finalisee, etc.).
  • transitions: Possible transitions between states (e.g., creation from brouillon to finalisee).

Using the Workflow#

Let’s create a Symfony command to test our workflow:

<?php

namespace App\Command;

use App\Entity\Commande;
use Symfony\Component\Console\Attribute\AsCommand;
use Symfony\Component\Console\Command\Command;
use Symfony\Component\Console\Input\InputInterface;
use Symfony\Component\Console\Output\OutputInterface;
use Symfony\Component\Console\Style\SymfonyStyle;
use Symfony\Component\Workflow\WorkflowInterface;

#[AsCommand(
    name: 'app:commande',
    description: 'Test the order workflow',
)]
class CommandeCommand extends Command
{
    public function __construct(readonly WorkflowInterface $commandeStateMachine)
    {
        parent::__construct();
    }

    protected function configure(): void
    {
    }

    protected function execute(InputInterface $input, OutputInterface $output): int
    {
        $io = new SymfonyStyle($input, $output);

        // Creating an order
        $comm = new Commande();
        $comm->setNumeroCommande(1);
        $comm->setEtatCommande('brouillon');
        
        // Displaying the initial state
        $io->text($comm->getEtatCommande());

        // Testing the "creation" transition
        $res = $this->commandeStateMachine->can($comm, 'creation');
        $io->text($res);

        // Applying the transition
        $this->commandeStateMachine->apply($comm, 'creation');
        $io->text($comm->getEtatCommande());

        // Attempting the "creation" transition again (fails)
        $this->commandeStateMachine->apply($comm, 'creation');
        
        return Command::SUCCESS;
    }
}

Exporting the Workflow#

You can also export your workflow as an image for better visualization:

bin/console workflow:dump commande | dot -Tpng -o workflow.png

Note: To run dot, install Graphviz.

Here’s an example of the generated image:

Symfony Workflow