Verbs

Attributes

#[StateId]

Link your event to its state(s) with the StateId attribute

1class YourEvent extends Event
2{
3 #[StateId(GameState::class)]
4 public int $game_id;
5 
6 #[StateId(PlayerState::class)]
7 public int $player_id;
8}

The StateId attribute takes a state_type, an optional alias string, and by default can automatically generate(autofill) a snowflake_id for you.

#[AppliesToState]

Another way to link states and events; like StateId, but using the attributes above the class instead of on each individual id.

1#[AppliesToState(GameState::class)]
2#[AppliesToState(PlayerState::class)]
3class RolledDice extends Event
4{
5 use PlayerAction;
6 
7 public function __construct(
8 public int $game_id,
9 public int $player_id,
10 public array $dice,
11 )
12}

AppliesToState has the same params as StateId, with an additional optional id param (after state_type) if you want to specify which prop belongs to which state.

1#[AppliesToState(state_type: GameState::class, id: foo_id)]
2#[AppliesToState(state_type: PlayerState::class, id: bar_id)]
3class RolledDice extends Event
4{
5 use PlayerAction;
6 
7 public function __construct(
8 public int $foo_id,
9 public int $bar_id,
10 public array $dice,
11 )
12}

Otherwise, with AppliesToState, Verbs will find the id for you based on your State's prefix (i.e. ExampleState would be example, meaning example_id or example_ids would be associated automatically).

#[AppliesToSingletonState]

Use the AppliesToSingletonState attribute on an event class to tell Verbs that it should always be applied to a single state (e.g. CountState) across the entire application (as opposed to having different counts for different states).

Because we're using a singleton state, there is no need for the event to have a $count_id.

1#[AppliesToSingletonState(CountState::class)]
2class IncrementCount extends Event
3{
4 public function apply(CountState $state)
5 {
6 $state->count++;
7 }
8}

In addition to your state_type param, you may also set an optional alias string.

#[AppliesToChildState]

Use the AppliesToChildState attribute on an event class to allow Verbs to access a nested state.

For our example, let's make sure our ParentState has a child_id property pointing to a ChildState by firing a ChildAddedToParent event:

1ChildAddedToParent::fire(parent_id: 1, child_id: 2);
2 
3// ChildAddedToParent.php
4#[AppliesToState(state_type: ParentState::class, id: 'parent_id')]
5#[AppliesToState(state_type: ChildState::class, id: 'child_id')]
6class ChildAddedToParent extends Event
7{
8 public int $parent_id;
9 
10 public int $child_id;
11 
12 public function applyToParentState(ParentState $state)
13 {
14 $state->child_id = $this->child_id;
15 }
16}
1class ParentState extends State
2{
3 public int $child_id;
4}
1class ChildState extends State
2{
3 public int $count = 0;
4}

Now that ParentState has a record of our ChildState, we can load the child through the parent with AppliesToChildState.

Let's show this by firing a NestedStateAccessed event with our new attribute:

1NestedStateAccessed::fire(parent_id: 1);
2 
3// NestedStateAccessed.php
4#[AppliesToChildState(
5 state_type: ChildState::class,
6 parent_type: ParentState::class,
7 id: 'child_id'
8)]
9class NestedStateAccessed extends Event
10{
11 #[StateId(ParentState::class)]
12 public int $parent_id;
13 
14 public function apply(ChildState $state)
15 {
16 $state->count++; // 1
17 }
18}

AppliesToChildState takes a state_type (your child state), parent_type, id (your child state id), and an optional alias string.

When you use AppliesToChildState, don't forget to also use StateId or AppliesToState to identify the parent_id.

#[Once]

Use above any handle() method that you do not want replayed.

1class YourEvent extends Event
2{
3 #[Once(YourState::class)]
4 public function handle()
5 {
6 //
7 }
8}

(You may also use Verbs::unlessReplaying, mentioned in one-time effects)