Configuring transitions | laravel-model-states | Spatie

 SPATIE

  Laravel Model States
=======================

spatie.be/open-source

  [Docs](https://spatie.be/docs)  [Laravel-model-states](https://spatie.be/docs/laravel-model-states/v2)  Working-with-transitions  Configuring transitions

 Version   v2   v1

 Other versions for crawler [v2](https://spatie.be/docs/laravel-model-states/v2) [v1](https://spatie.be/docs/laravel-model-states/v1)

- [ Introduction ](https://spatie.be/docs/laravel-model-states/v2/01-introduction)
- [ Postcardware ](https://spatie.be/docs/laravel-model-states/v2/02-postcardware)
- [ Requirements ](https://spatie.be/docs/laravel-model-states/v2/03-requirements)
- [ Installation &amp; setup ](https://spatie.be/docs/laravel-model-states/v2/04-installation-setup)
- [ Questions and issues ](https://spatie.be/docs/laravel-model-states/v2/05-questions-issues)
- [ Changelog ](https://spatie.be/docs/laravel-model-states/v2/06-changelog)
- [ About us ](https://spatie.be/docs/laravel-model-states/v2/07-about-us)

Working with states
-------------------

- [ Configuring states ](https://spatie.be/docs/laravel-model-states/v2/working-with-states/01-configuring-states)
- [ Serializing states ](https://spatie.be/docs/laravel-model-states/v2/working-with-states/02-serializing-states)
- [ Listing states ](https://spatie.be/docs/laravel-model-states/v2/working-with-states/03-listing-states)

Working with transitions
------------------------

- [ Configuring transitions ](https://spatie.be/docs/laravel-model-states/v2/working-with-transitions/01-configuring-transitions)
- [ Custom transition classes ](https://spatie.be/docs/laravel-model-states/v2/working-with-transitions/02-custom-transition-classes)
- [ Dependency injection in transition classes ](https://spatie.be/docs/laravel-model-states/v2/working-with-transitions/03-dependency-injection-in-transition-classes)
- [ Retrieving transitionable states ](https://spatie.be/docs/laravel-model-states/v2/working-with-transitions/04-retrieving-transitionable-states)
- [ Transition events ](https://spatie.be/docs/laravel-model-states/v2/working-with-transitions/05-transition-events)
- [ Custom default transition class ](https://spatie.be/docs/laravel-model-states/v2/working-with-transitions/06-custom-default-transition-class)

Querybuilder support
--------------------

- [ State scopes ](https://spatie.be/docs/laravel-model-states/v2/querybuilder-support/01-state-scopes)

Request validation
------------------

- [ State validation rule ](https://spatie.be/docs/laravel-model-states/v2/request-validation/01-state-validation-rule)

 Configuring transitions
=======================

###  On this page

1. [ Ignoring same state transitions ](#content-ignoring-same-state-transitions)
2. [ Allow multiple transitions at once ](#content-allow-multiple-transitions-at-once)
3. [ Allowing multiple from states ](#content-allowing-multiple-from-states)
4. [ Using transitions ](#content-using-transitions)

Transitions can be used to transition the state of a model from one to another, in a structured and safe way.

You can specify which states are allowed to transition from one to another, and if you want to handle side effects or have more complex transitions, you can also provide custom transition classes.

Transitions are configured in the `config` method on your state classes.

```
abstract class PaymentState extends State
{
    // …

    public static function config(): StateConfig
    {
        return parent::config()
            ->allowTransition(Pending::class, Paid::class)
            ->allowTransition(Pending::class, Failed::class, PendingToFailed::class);
    }
}
```

In this example we're using both a simple transition, and a custom one. You can also allow all transitions for all registered states. Concrete states extending the abstract state class that are located in the same directory as the abstract state class will be automatically registered:

```
abstract class PaymentState extends State
{
    // …

    public static function config(): StateConfig
    {
        return parent::config()
            ->allowAllTransitions();
    }
}
```

Transitions can then be used like so:

```
$payment->state->transitionTo(Paid::class);
```

This line will only work when a valid transition was configured. If the initial state of `$payment` already was `Paid`, a `\Spatie\ModelStates\Exceptions\TransitionNotFound` will be thrown instead of changing the state.

Ignoring same state transitions
-----------------------------------------------------------------------------------------------------------------------------------------------------

In some cases you may want to handle transition to same state without manually setting `allowTransition`, you can call `ignoreSameState`

Please note that the `StateChanged` event will fire anyway.

```
abstract class PaymentState extends State
{
    // …

    public static function config(): StateConfig
    {
        return parent::config()
            ->ignoreSameState()
            ->allowTransition([Created::class, Pending::class], Failed::class, ToFailed::class);
    }
}
```

It also works with `IgnoreSameState` Attribute

```
#[IgnoreSameState]
abstract class PaymentState extends State
{
    //...
}
```

Allow multiple transitions at once
--------------------------------------------------------------------------------------------------------------------------------------------------------------

A little shorthand `allowTransitions` can be used to allow multiple transitions at once:

```
abstract class PaymentState extends State
{
    // …

    public static function config(): StateConfig
    {
        return parent::config()
            ->allowTransitions([
                [Pending::class, Paid::class],
                [Pending::class, Failed::class, PendingToFailed::class],
            ]);
    }
}
```

Allowing multiple from states
-----------------------------------------------------------------------------------------------------------------------------------------------

If you've got multiple states that can transition to the same state, you can define all of them in one `allowTransition` call:

```
abstract class PaymentState extends State
{
    // …

    public static function config(): StateConfig
    {
        return parent::config()
            ->allowTransition([Created::class, Pending::class], Failed::class, ToFailed::class);
    }
}
```

Using transitions
-----------------------------------------------------------------------------------------------------------

Transitions can be used by calling the `transitionTo` method on the state field like so:

```
$payment->state->transitionTo(Paid::class);
```
