In Sylius, the default approach to managing frequent changes in the system is through the Symfony Workflow, which offers a highly flexible and well-organized solution. However, Sylius also provides the option to use the Winzou State Machine if preferred.
Both options allow you to define a set of states stored on an entity and manage transitions between them. Additionally, each state machine can be configured with callbacks—events triggered during specific transitions—making it easy to customize how your system responds to changes.
States
States of a state machine are defined as constants on the model of an entity that the state machine is controlling.
How to configure states? Let’s see the example from the Checkout state machine.
On the graph it would be the connection between two states, defining that you can move from one state to another subsequently.
How to configure transitions? Let’s see the example of our Checkout state machine. Having states configured we can have a transition between the cart state to the addressed state.
# CoreBundle/Resources/config/app/state_machine/sylius_order_checkout.ymlwinzou_state_machine:sylius_order_checkout:transitions:address: from: [cart, addressed, shipping_selected, shipping_skipped, payment_selected, payment_skipped] # here you specify which state is the initial
to:addressed
Listeners / Callbacks
Listeners can be used to execute actions in reaction to a given transition in Symfony Workflow.
How do you configure Listeners attached to events in Symfony Workflow?
You need to create a Listener that will be waiting for the chosen transition and will invoke the desired behaviors.
Below you can see the ProcessCartListner configured for the order_checkout state machine's transitions.
Callbacks in Winzou State Machine are used to execute some code before or after applying transitions. Winzou StateMachineBundle adds the ability to use Symfony services in the callbacks.
How do you configure callbacks in Winzou State Machine?
Having a configured transition, you can attach a callback to it before or after. A callback is simply a method of a service you want to be executed.
Below you can see how the sylius_process_cart callback is configured on the sylius_order_checkout state machine.
# CoreBundle/Resources/config/app/state_machine/sylius_order_checkout.ymlwinzou_state_machine:sylius_order_checkout:callbacks: # callbacks may be called before or after specified transitions, in the checkout state machine we've got callbacks only after transitions
after:sylius_process_cart:on: ["select_shipping","address","select_payment","skip_shipping","skip_payment"]do: ["@sylius.order_processing.order_processor","process"]args: ["object"]priority:-200
Configuration
In order to use a state machine, you have to define a graph beforehand. A graph is a definition of states, transitions, and optionally callbacks - all attached to an object from your domain. Multiple graphs may be attached to the same object.
In Sylius the best example of a state machine is the one from checkout. It has seven states available: cart, addressed, shipping_selected, shipping_skipped, payment_skipped, payment_selected and completed - which can be achieved by applying some transitions to the entity. For example, when selecting a shipping method during the shipping step of checkout we should apply the select_shipping transition, and after that the state would become shipping_selected.