Follow

Follow
Spatie Model states upgrading V1 to V2

Spatie Model states upgrading V1 to V2

Paul Hennell's photo
Paul Hennell
·Apr 29, 2022

I've got quite into the power of Spaties [laravel-model-states](https://spatie.be/docs/laravel-model-states/v2/01-introduction) package. I refactored an app a few years ago, and the state pattern and use of classes for states and transitions cleared up so much confusion.

Upgrading to Laravel 9 though I needed to change to spatie models states v2. Which was more involved because the state system changed heavily to use Laravel's casting system.

While not crazy complicated, I had enough states and have used this on several apps, so I made notes for me to follow with each state to avoid having to cycle between different doc pages.

In your state-using model you need to add the casts attribute linking to the abstract state class:

protected $casts = [
        'status' => ProductState::class,
    ];

Take your registered states code from the model:

///from Model
protected function registerStates(): void
    {
 $this->addState('status', ProductState::class)
            ->default(Active::class)
            ->allowTransition(
                [Development::class, Special::class, Active::class, TBD::class],
                Discontinued::class,
                toDiscontinuedTransition::class
            )
            ->allowTransition(
                [Development::class, Special::class, TBD::class, Discontinued::class],
                Active::class
            )
            ->allowTransition(
                [Special::class, Active::class, Discontinued::class],
                TBD::class
            )
            ->allowTransition(
                [Development::class, Active::class, TBD::class, Discontinued::class],
                Special::class
            )
            ->allowTransition(
                [Active::class, Special::class],
                Development::class
            );
}

And move that to your abstract state class:

//In ProductState.php
public static function config(): StateConfig
    {
        return parent::config()
            ->default(Active::class)
            ->allowTransition(
                [Development::class, Special::class, Active::class, TBD::class],
                Discontinued::class,
                toDiscontinuedTransition::class
            )
            ->allowTransition(
                [Development::class, Special::class, TBD::class, Discontinued::class],
                Active::class
            )
            ->allowTransition(
                [Special::class, Active::class, Discontinued::class],
                TBD::class
            )
            ->allowTransition(
                [Development::class, Active::class, TBD::class, Discontinued::class],
                Special::class
            )
            ->allowTransition(
                [Active::class, Special::class],
                Development::class
            );
    }

Transitioning inside states:

In my states I had a lot of $this->model->transitionTo() to change between states. The new system is $this->transitionTo() a quick find and replace across the states folder fixed that.

There's also a couple of changed methods - all my states worked fine in tests, but there were a few places I was passing a field no longer needed that I took out for completeness.

Review the full changed method list here

 
Share this