sebdesign / laravel-state-machine

Winzou State Machine service provider for Laravel
MIT License
327 stars 57 forks source link

Issue defining callbacks in state-machine.php #62

Closed pablosebastianr closed 2 years ago

pablosebastianr commented 2 years ago

I have a laravel 9 project, with php 8.1 laravel-state-machine version 3.3.0

These don't work

'callbacks' => [
    'after' => [
        'after_registrar' => [
            'on' => 'enviar_documentacion',
            'do' => [\App\Actions\AfterTramiteTransition::class, 'run'], 
            'args' => ['event', 'object'],
        ],
    ],
],

'callbacks' => [
    'after' => [
        'after_enviar_documentacion' => [
            'on' => 'enviar_documentacion',
            'do' => '\App\Actions\AfterTramiteTransition@run',
            'args' => ['event', 'object'],
        ],
    ],
],

The error I get is :

  TypeError

  SM\Callback\Callback::filterCallable(): Return value must be of type callable, string returned

  at vendor/winzou/state-machine/src/SM/Callback/Callback.php:142

or Return value must be of type callable, array returned if I used the first one.

Digging a bit into the winzou library I found SM\Callback\CallbackInterface That's an invokable class.

If I do this it works


'callbacks' => [
    'after' => [
        'after_enviar_documentacion' => [
            'on' => 'enviar_documentacion',
            'do' => new \App\Actions\AfterTramiteTransition(),
            'args' => ['event', 'object'],
        ],
    ],
],

But the problem is with Laravel with that approach. php artisan config:cahe will fail because it can't serialize the config files.

Since that class is an invokable I tried 'do' => \App\Actions\AfterTramiteTransition::class, but no luck, same error

I don't know what I'm doing wrong or what changed but I have another project in Laravel 8, with laravel-state-machine 3.2.1 and I have no issues using 'do' => [\App\MyClass:class, 'method'] to define callbacks.

sebdesign commented 2 years ago

Hello,

That's quite strange. Can you tell me the version of the "winzou/state-machine" that is installed?

composer show | grep winzou/state-machine
sebdesign commented 2 years ago

I figured out what's happening.

The run method on the App\Actions\AfterTramiteTransition class is not a static method, so PHP cannot call it statically. This package tries to resolve the instance of the App\Actions\AfterTramiteTransition from the container, in order to call it normally. Since the class is not registered in the Laravel container, that doesn't work.

You need to register App\Actions\AfterTramiteTransition in your AppServiceProvider (or any other service provider) like this:

public function register()
{
    $this->bind(\App\Actions\AfterTramiteTransition::class);
}

or like this:

public array $bindings = [
    \App\Actions\AfterTramiteTransition => \App\Actions\AfterTramiteTransition::class,
];

or like this:

public array $bindings = [
    \App\Actions\AfterTramiteTransition => null,
];
pablosebastianr commented 2 years ago

Thanks you ! That was the issue. Either defining the the method as static or manually registering the class in Laravel's container.