winzou StateMachineBundle

repository·master·Indexed 43 days ago

https://github.com/winzou/statemachinebundle

A lightweight PHP state machine bundle for Symfony that allows defining states, transitions, and lifecycle callbacks for domain objects via configuration. It includes a factory for instantiating state machines and a debug:winzou:state-machine command for inspecting configurations.

Tokens
2.2K
Snippets
7
Records
8
Agent score
6%

What's inside StateMachineBundle

  1. How state machines and factories work together

    master

    A State Machine is the object that manipulates your domain object. A state machine is specific to a unique combination of an object + a graph.

    Because you cannot manually instantiate a state machine for every object, you use the SM\Factory\Factory service. The factory takes your domain object and the name of the graph you want to apply, and returns the appropriate state machine instance.

    To use it, inject SM\Factory\Factory into your service or controller.

    public function myAwesomeAction($id, \SM\Factory\Factory $factory)
    {
        // Get your domain object
        $article = $this->getRepository('MyAwesomeBundle:Article')->find($id);
        
        // Get the state machine for this object, and graph called "simple"
        $articleSM = $factory->get($article, 'simple');
    }
  2. Configure transition callbacks

    master

    Callbacks allow you to execute logic during the transition lifecycle. You can use Symfony services to perform these actions. There are three main types of callbacks:

    1. guard: Used to test if a transition can be applied. If the callback returns false, the transition is blocked. Use the guard key in configuration.
    2. before: Executed immediately before the transition is applied to the object. Use the before key.
    3. after: Executed immediately after the transition has been applied. Use the after key.

    Each callback configuration requires:

    • on: The name of the transition this callback applies to.
    • do: An array containing the service ID (prefixed with @) and the method name to call.
    • args: An array of arguments to pass to the method. Use 'object' to pass the domain object itself.
    # Example callback configuration
    callbacks:
        guard:
            my_guard:
                on: 'submit_changes'
                do: ['@my.service', 'canSubmit']
                args: ['object']
        before:
            my_before:
                on: 'create'
                do: ['@my.service', 'doSomething']
                args: ['object']
        after:
            my_after:
                on: 'publish'
                do: ['@my.service', 'notify']
                args: ['object', '"Message"']
  3. Configure a state machine graph

    master

    A graph defines the states, transitions, and callbacks for a specific domain object. You configure these in your Symfony configuration file (e.g., app/config/config.yml).

    Key configuration keys:

    • class: The FQCN of your domain object.
    • property_path: The property on your object that holds the current state (defaults to state).
    • graph: The name of the graph (defaults to default).
    • states: A list of all valid states.
    • transitions: A mapping of transition names to their from (source states) and to (target state) definitions.
    • callbacks: Logic to execute during the transition lifecycle.
    winzou_state_machine:
        my_bundle_article:
            class: My\Bundle\Entity\Article
            property_path: state
            graph: simple
            states:
                - new
                - pending_review
                - awaiting_changes
                - accepted
                - published
                - rejected
            transitions:
                create:
                    from: [new]
                    to: pending_review
                ask_for_changes:
                    from: [pending_review, accepted]
                    to: awaiting_changes
                submit_changes:
                    from: [awaiting_changes]
                    to: pending_review
                approve:
                    from: [pending_review, rejected]
                    to: accepted
                publish:
                    from: [accepted]
                    to: published
            callbacks:
                guard:
                    guard_on_submitting:
                        on: 'submit_changes'
                        do: ['@my.awesome.service', 'isSubmittable']
                        args: ['object']
                before:
                    update_reviewer:
                        on: 'create'
                        do: ['@my.awesome.service', 'update']
                        args: ['object']
                after:
                    email_on_publish:
                        on: 'publish'
                        do: ['@my.awesome.service', 'sendEmail']
                        args: ['object', '"Email title"']
  4. Use the State Machine API to manipulate objects

    master

    Once you have obtained a state machine instance via the factory, you can use the following methods to manage the object's state:

    • $articleSM->can('transition_name'): Returns true if the transition is currently possible given the object's state, otherwise false.
    • $articleSM->apply('transition_name'): Executes the transition, moving the object to the new state and triggering any configured callbacks.
    • $articleSM->getState(): Retrieves the current state of the object.
    • $articleSM->getPossibleTransitions(): Returns a list of all transitions that can currently be applied.
    // Check if a transition can be applied
    if ($articleSM->can('create')) {
        $articleSM->apply('create');
    }
    
    // Get current state
    $currentState = $articleSM->getState();
    
    // Get available transitions
    $transitions = $articleSM->getPossibleTransitions();
  5. Debug state machine configurations with debug:winzou:state-machine

    master

    The debug:winzou:state-machine command allows you to inspect the configuration of your defined state machines. It outputs a summary of all configured states, transitions (including their 'from' and 'to' states), and any registered callbacks.

    If you do not provide a specific state machine key as an argument, the command will enter an interactive mode and present a list of available state machines for you to choose from.

    php bin/console debug:winzou:state-machine [key]