PHP code example of ahmedashraf093 / better-eloquent-state-machine

1. Go to this page and download the library: Download ahmedashraf093/better-eloquent-state-machine library. Choose the download type require.

2. Extract the ZIP file and open the index.php.

3. Add this code to the index.php.
    
        
<?php
require_once('vendor/autoload.php');

/* Start to develop here. Best regards https://php-download.com/ */

    

ahmedashraf093 / better-eloquent-state-machine example snippets


$salesOrder->status; // 'pending', 'approved', 'declined' or 'processed'

$salesOrder->fulfillment; // null, 'pending', 'completed'

$salesOrder->status()->transitionTo('approved');

$salesOrder->fulfillment()->transitionTo('completed');

//With custom properties
$salesOrder->status()->transitionTo('approved', [
    'comments' => 'Customer has available credit',
]);

//With responsible
$salesOrder->status()->transitionTo('approved', [], $responsible); // auth()->user() by default

# php named args example
$salesOrder->status()->transitionTo(to: 'approved', responsible: auth()->user())

$salesOrder->status()->canBe('approved');

$salesOrder->status()->canBe('declined');

$salesOrder->status()->is('approved');

$salesOrder->status()->responsible(); // User|null

$salesOrder->status()->was('approved');

$salesOrder->status()->timesWas('approved');

$salesOrder->status()->whenWas('approved');

$salesOrder->fulfillment()->snapshowWhen('completed');

$salesOrder->status()->history()->get();

use Ashraf\EloquentStateMachine\StateMachines\StateMachine;

class StatusStateMachine extends StateMachine
{
    public function recordHistory(): bool
    {
        return false;
    }

    public function transitions(): array
    {
        return [
            //
        ];
    }

    public function defaultState(): ?string
    {
        return null;
    }
}

public function transitions(): array
{
    return [
        'pending' => [
            'approved' => fn($model, $who): bool => true, 
            'declined' => fn($model, $who): bool => $who->getTable() === User::tableName(), // only allow users to decline
        ],
        'approved' => [
            'processed' // no need for extra validation
        ],
    ];
}

public function transitions(): array
{
    return [
        '*' => ['approved', 'declined'], // From any to 'approved' or 'declined'
        'approved' => '*', // From 'approved' to any
        '*' => '*', // From any to any
    ];
}

public function defaultState(): ?string
{
    return 'pending'; // it can be null too
}

public function recordHistory(): bool
{
    return true;
}

use Ashraf\EloquentStateMachine\Traits\HasStateMachines;
use App\StateMachines\StatusStateMachine;

class SalesOrder extends Model
{
    Use HasStateMachines;

    /**
     *  mark the `status` to be controlled by `StatusStateMachine`
     */
    public $stateMachines = [
        'status' => StatusStateMachine::class
    ];
}

'status' => StatusStateMachine::class,
'fulfillment_status' => FulfillmentStatusStateMachine::class

status();
fulfillment_status(); // or fulfillmentStatus()

$salesOrder->status()->transitionTo($to = 'approved');

# PHP8 named args
$salesOrder->status()->transitionTo(to: 'approved');

$salesOrder->status()->transitionTo($to = 'approved', $customProperties = [
    'comments' => 'All ready to go'
]);

# PHP8 named args
$salesOrder->status()->transitionTo(
    to: 'approved', 
    customProperties: [
        'comments' => 'All ready to go'
    ]
);

$salesOrder->status()->transitionTo(
    $to = 'approved',
    $customProperties = [],
    $responsible = User::first()
);

# PHP8 named args
$salesOrder->status()->transitionTo(
    to: 'approved',
    responsible: User::first()
);

$salesOrder->status()->was('approved'); // true or false

$salesOrder->status()->timesWas('approved'); // int

$salesOrder->status()->whenWas('approved'); // ?Carbon

$salesOrder->status()->snapshotWhen('approved');

$salesOrder->status()->snapshotsWhen('approved');

$salesOrder->status()->history()->get();

$salesOrder->status()->history()
    ->from('pending')
    ->to('approved')
    ->withCustomProperty('comments', 'like', '%good%')
    ->get();

SalesOrder::with()
    ->whereHasStatus(function ($query) {
        $query
            ->withTransition('pending', 'approved')
            ->withResponsible(auth()->id())
        ;
    })
    ->whereHasFulfillment(function ($query) {
        $query
            ->transitionedTo('complete')
        ;
    })
    ->get();

$salesOrder->status()->getCustomProperty('comments');

$salesOrder->status()->snapshotWhen('approved')->getCustomProperty('comments');

$salesOrder->status()->responsible();

$salesOrder->status()->snapshotWhen('approved')->responsible;

$salesOrder = SalesOrder::create([
    'total' => 100,
]);

$salesOrder->total = 200;

$salesOrder->status()->transitionTo('approved');

$salesOrder->changedAttributesNames(); // ['total']

$salesOrder->changedAttributeOldValue('total'); // 100
$salesOrder->changedAttributeNewValue('total'); // 200

public function transitions(): array
{
    return [
        'pending' => [
            'approved' => fn($model, $who): bool => true, 
            'declined' => fn($model, $who): bool => $who->getTable() === User::tableName(), // only allow users to decline
            #             ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
        ],
        'approved' => [
            'processed' // no need for extra validation
        ],
    ];
}
 
fn($model, $who): bool => $who->getTable() === User::tableName()

public function transitions(): array
{
    return [
        'pending' => [
            'approved' => fn($model, $who): bool => $who->hasRole('sales_manager') && $who->can('approve', $model),
            'declined' => fn($model, $who): bool => $who->getTable() === User::tableName(), // only allow users to decline
        ],
        'approved' => [
            'processed' // no need for extra validation
        ],
    ];
}

$salesOrder->status()->stateMachine->availableTransitions(); // ['approved', 'declined']

$user = User::first();
$salesOrder->status()->stateMachine->availableTransitions($user); // ['approved']

class StatusStateMachine extends StateMachine
{
    public function beforeTransitionHooks(): array
    {
        return [
            'approved' => [
                function ($to, $model) {
                    // Dispatch some job BEFORE "approved changes to $to"
                },
                function ($to, $model) {
                    // Send mail BEFORE "approved changes to $to"
                },
            ],
        ];
    }

    public function afterTransitionHooks(): array
    {
        return [
            'processed' => [
                function ($from, $model) {
                    // Dispatch some job AFTER "$from transitioned to processed"
                },
                function ($from, $model) {
                    // Send mail AFTER "$from transitioned to processed"
                },
            ],
        ];
    }
}
bash
php artisan vendor:publish --provider="Ashraf\EloquentStateMachine\LaravelEloquentStateMachinesServiceProvider" --tag="migrations"
bash
php artisan migrate