sebdesign/laravel-state-machine

Listener per graph

MartinP7r opened this issue ยท 3 comments

Hi @sebdesign , me again with the constant questions. ๐Ÿ˜…

I'm trying to figure out how to listen to all POST_TRANSITION events for one specific graph. By your readme it seems to be either listening to all POST_TRANSITION events for all graphs via SMEvents::POST_TRANSITION in EventServiceProvider or callbacks for every state transition one by one.

The use case is filtering all transitions going away from one state of one specific graph in order to reset some property afterwards. E.g. there's a locked state that's associated with a person_in_charge field that has to be reset to null whenever the graph transitions away from the locked state.

edit: if the answer is hooking up after callbacks for every single transition, that's completely fine. I was just wondering if there is some kind of wildcard feature that I'm missing in this regard.

edit2: if nothing else, I could probably do something like:

public function handle(TransitionEvent $event)
{
    $graph = $event->getStateMachine()->getGraph();
    if ($graph !== 'accounting_state') return;
    // (...)
}

but it would fire a lot of unnecessary listener calls (though I'm not entirely sure how events and listeners impact performance in that regard).

Cheers,
Martin

Hey there,

I haven't found the time to answer the other issue, but this one is simpler I think. :)

Personally I would avoid using the POST_TRANSITION because checking the graph type each time would be unnecessary as you said.

I think you can get use an after callback this way:

'after' => [
    'from_locked' => [
        'from' => 'locked',
        'do' => ['object', 'removePersonInCharge'],
    ],
],

After any transition that goes away from the locked state, call the removePersonInCharge method on the model. The removePersonInCharge method would be a method where you set the person_in_charge field to null (that's just an example).

If you don't want to create a removePersonInCharge method, I believe you can use the do clause like this:

'do' => ['object', 'setAttribute'],
'args' => ['"person_in_charge"', 'null'], // notice  the double quotes on the field

The setAttribute method is available on Eloquent models.

Wow, thanks. I did not realize that callbacks work that way with to/from as well. I guess I should read your documentation and the one of the original winzou/state-machine more closely ๐Ÿ˜…. This solves my problem and here, thanks so much.

Sorry I did not get around to dive into your explanation to my other question, yet. Will do as soon as possible.

Stay safe!