Customizing State Machines¶

Warning

Not familiar with the State Machine concept? Read the docs here!

Note

Customizing logic via State Machines vs. Events

The logic in which Sylius operates can be customized in two ways. First of them is using the state machines: what is really useful when you need to modify business logic for instance modify the flow of the checkout, and the second is listening on the kernel events related to the entities, which is helpful for modifying the HTTP responses visible directly to the user, like displaying notifications, sending emails.

How to customize a State Machine?¶

Tip

You can browse the full implementation of these examples on this GitHub Pull Request.

How to add a new state?¶

Let’s assume that you would like to add a new state to the Order state machine. You will need to add these few lines to the config/packages/_sylius.yaml:

# config/packages/_sylius.yaml
winzou_state_machine:
    sylius_order:
        states:
            new_custom_state: ~ # here name your state as you wish

After that your new step will be available alongside other steps that already were defined in that state machine.

Tip

Run php bin/console debug:winzou:state-machine sylius_order to check if the state machine has changed to your implementation.

How to add a new transition?¶

Let’s assume that you would like to add a new transition to the Order state machine, that will allow moving from the cancelled state backwards to new. Let’s call it “restoring”.

You will need to add these few lines to the config/packages/_sylius.yaml:

# config/packages/_sylius.yaml
winzou_state_machine:
    sylius_order:
        transitions:
            restore:
                from: [cancelled]
                to: new

After that your new transition will be available alongside other transitions that already were defined in that state machine.

Tip

Run php bin/console debug:winzou:state-machine sylius_order to check if the state machine has changed to your implementation.

How to remove a state and its transitions?¶

Warning

If you are willing to remove a state or a transition you have to override the whole states/transitions section of the state machine you are willing to modify. See how we do it in the customization of the Checkout process.

How to add a new callback?¶

Warning

From Sylius v1.11 we strongly encourage to use priorities to any callback you are adding. If you declare too many callbacks per action, this could lead to unexpected execution behavior.

Let’s assume that you would like to add a new callback to the Product Review state machine, that will do something on an already defined transition.

You will need to add these few lines to the config/packages/_sylius.yaml:

# config/packages/_sylius.yaml
winzou_state_machine:
    sylius_product_review:
        callbacks:
            after:
                sylius_update_rating:
                    # here you are choosing the transition on which the action should take place - we are using the one we have created before
                    on: ["accept"]
                    # use service and its method here
                    do: ["@App\\ProductReview\\Mailer\\ConfirmationMailer", "sendEmail"]
                    # this will be the object of an Order here
                    args: ["object"]
                    priority: 100

Tip

Declared priorities will be executed in ascending order. If you are adding callback to existing state, you can find declared states and callbacks under path Sylius/Bundle/CoreBundle/Resources/config/app/state_machine.

Tip

If you want to see the implementation of ConfirmationMailer check it on this GitHub Pull Request.

After that your new callback will be available alongside other callbacks that already were defined in that state machine and will be called on the desired transition.

How to modify a callback?¶

If you would like to modify an existent callback of for example the state machine of ProductReviews, so that it does not count the average rating but does something else - you need to add these few lines to the config/packages/_sylius.yaml:

# config/packages/_sylius.yaml
winzou_state_machine:
    sylius_review:
        callbacks:
            after:
                update_price:
                    on: "accept"
                    # here you can change the service and its method that is called for your own service
                    do: ["@sylius.review.updater.your_service", update]
                    args: ["object"]
                    priority: 100

How to disable a callback?¶

If you would like to turn off a callback of a state machine you need to set its disabled option to true. On the example of the state machine of ProductReview, we can turn off the update_price callback:

# config/packages/_sylius.yaml
winzou_state_machine:
    sylius_review:
        callbacks:
            after:
                update_price:
                    disabled: true

Good to know¶

See also

All the customizations can be done either in your application directly or in Plugins!