Skip to main content

Overview

The WorkflowStub class provides the primary interface for creating, starting, querying, and controlling workflow instances. It acts as a handle to interact with both new and existing workflows.

Traits Used

  • Awaits - Provides methods for awaiting conditions
  • AwaitWithTimeouts - Adds timeout support to await operations
  • Continues - Enables workflow continuation
  • Fakes - Provides testing/mocking support
  • Macroable - Allows dynamic method addition
  • SideEffects - Handles non-deterministic operations
  • Timers - Provides timer functionality
  • Versions - Supports workflow versioning

Constants

DEFAULT_VERSION
int
default:"-1"
The default version number for workflows

Static Methods

make()

public static function make($class): static
Creates a new workflow instance without starting it.
class
string
required
The fully qualified workflow class name
Returns: A new WorkflowStub instance

Example

use Workflow\WorkflowStub;

$workflow = WorkflowStub::make(OrderWorkflow::class);
$workflow->start($order);

load()

public static function load($id)
Loads an existing workflow by ID.
id
string
required
The workflow instance ID (UUID)
Returns: A WorkflowStub instance for the loaded workflow

Example

$workflow = WorkflowStub::load('01234567-89ab-cdef-0123-456789abcdef');
$status = $workflow->status();

fromStoredWorkflow()

public static function fromStoredWorkflow(StoredWorkflow $storedWorkflow): static
Creates a workflow stub from an existing StoredWorkflow model.
storedWorkflow
StoredWorkflow
required
The stored workflow model instance
Returns: A new WorkflowStub instance

Example

$stored = StoredWorkflow::where('class', OrderWorkflow::class)->first();
$workflow = WorkflowStub::fromStoredWorkflow($stored);

getContext()

public static function getContext(): \stdClass
Returns the current workflow execution context. Returns: Object with properties: storedWorkflow, index, now, replaying

Example

public function execute()
{
    $context = WorkflowStub::getContext();
    $isReplaying = $context->replaying;
    $currentIndex = $context->index;
}

setContext()

public static function setContext($context): void
Sets the workflow execution context.
context
array|object
required
Context object with workflow execution state

Example

WorkflowStub::setContext([
    'storedWorkflow' => $storedWorkflow,
    'index' => 0,
    'now' => Carbon::now(),
    'replaying' => false,
]);

now()

public static function now()
Returns the current deterministic timestamp for the workflow. Returns: Carbon instance representing the workflow’s current time

Example

public function execute()
{
    // Don't use Carbon::now() - use WorkflowStub::now()
    $currentTime = WorkflowStub::now();
    
    yield ActivityStub::make(ScheduleReminder::class, $currentTime->addHours(24));
}

connection()

public static function connection()
Returns the queue connection for the current workflow. Returns: String connection name or null

queue()

public static function queue()
Returns the queue name for the current workflow. Returns: String queue name or null

isUpdateMethod()

public static function isUpdateMethod(string $class, string $method): bool
Checks if a method is marked with the UpdateMethod attribute.
class
string
required
The workflow class name
method
string
required
The method name to check
Returns: Boolean indicating if the method is an update method

getDefaultProperties()

public static function getDefaultProperties(string $class): array
Returns default property values for a workflow class.
class
string
required
The workflow class name
Returns: Array of property names and default values

Instance Methods

id()

public function id()
Returns the workflow instance ID. Returns: String UUID

Example

$workflow = WorkflowStub::make(OrderWorkflow::class);
$workflow->start($order);

$id = $workflow->id();
// Returns: "01234567-89ab-cdef-0123-456789abcdef"

start()

public function start(...$arguments): void
Starts the workflow with the provided arguments.
arguments
mixed
required
Variable arguments passed to the workflow execute method

Example

$workflow = WorkflowStub::make(OrderWorkflow::class);
$workflow->start($order, new WorkflowOptions(
    connection: 'redis',
    queue: 'high-priority'
));

startAsChild()

public function startAsChild(
    StoredWorkflow $parentWorkflow,
    int $index,
    $now,
    ...$arguments
): void
Starts the workflow as a child of another workflow.
parentWorkflow
StoredWorkflow
required
The parent workflow’s stored model
index
int
required
The parent workflow’s execution index
now
Carbon|string
required
The parent workflow’s current timestamp
arguments
mixed
required
Arguments for the child workflow

status()

public function status(): string|bool
Returns the workflow’s current status class. Returns: Fully qualified status class name

Example

$status = $workflow->status();

if ($status === WorkflowCompletedStatus::class) {
    echo "Workflow completed!";
}

completed()

public function completed(): bool
Checks if the workflow has completed successfully. Returns: Boolean

Example

if ($workflow->completed()) {
    $result = $workflow->output();
}

created()

public function created(): bool
Checks if the workflow is in created state (not yet started). Returns: Boolean

failed()

public function failed(): bool
Checks if the workflow has failed. Returns: Boolean

Example

if ($workflow->failed()) {
    $exceptions = $workflow->exceptions();
    foreach ($exceptions as $exception) {
        Log::error('Workflow error', ['error' => $exception]);
    }
}

running()

public function running(): bool
Checks if the workflow is currently running (not completed or failed). Returns: Boolean

output()

public function output()
Returns the workflow’s output value after completion. Returns: Mixed value returned by the workflow’s execute method, or null if not completed

Example

$workflow = WorkflowStub::load($workflowId);

if ($workflow->completed()) {
    $result = $workflow->output();
    echo "Order total: " . $result['total'];
}

logs()

public function logs()
Returns the workflow’s execution logs. Returns: Collection of log entries

exceptions()

public function exceptions()
Returns exceptions that occurred during workflow execution. Returns: Collection of exception records

fresh()

public function fresh(): static
Refreshes the workflow state from the database. Returns: The workflow stub instance

Example

$workflow->fresh()->status();

resume()

public function resume(): void
Resumes a paused workflow by dispatching it to the queue.

Example

$workflow = WorkflowStub::load($workflowId);
$workflow->resume();

fail()

public function fail($exception): void
Manually fails the workflow with an exception.
exception
Throwable
required
The exception that caused the failure

Example

try {
    // Some operation
} catch (\Exception $e) {
    $workflow->fail($e);
}

next()

public function next(
    $index,
    $now,
    $class,
    $result,
    bool $shouldSignal = true
): void
Records the next step in workflow execution history.
index
int
required
The execution index
now
Carbon|string
required
The timestamp for this step
class
string
required
The class that was executed
result
mixed
required
The result of the execution
shouldSignal
bool
default:"true"
Whether to dispatch the workflow to continue

Magic Methods

__call()

public function __call($method, $arguments)
Handles signal, query, and update method calls dynamically.
  • Signal Methods: Send asynchronous signals to the workflow
  • Query Methods: Read workflow state without side effects
  • Update Methods: Modify workflow state and optionally trigger execution

Example

use Workflow\Workflow;
use Workflow\SignalMethod;
use Workflow\QueryMethod;
use Workflow\UpdateMethod;

class OrderWorkflow extends Workflow
{
    private string $status = 'pending';
    private int $quantity = 0;

    #[SignalMethod]
    public function cancelOrder(): void
    {
        $this->status = 'cancelled';
    }

    #[QueryMethod]
    public function getStatus(): string
    {
        return $this->status;
    }

    #[UpdateMethod]
    public function updateQuantity(int $qty): void
    {
        $this->quantity = $qty;
    }
}

// Using the workflow stub
$workflow = WorkflowStub::make(OrderWorkflow::class);
$workflow->start($order);

// Call signal method
$workflow->cancelOrder();

// Call query method
$status = $workflow->getStatus();

// Call update method
$workflow->updateQuantity(5);

Complete Example

use Workflow\WorkflowStub;
use App\Workflows\OrderWorkflow;
use App\Models\Order;

// Create and start a new workflow
$order = Order::find(1);
$workflow = WorkflowStub::make(OrderWorkflow::class);
$workflow->start($order);

// Store the workflow ID
$workflowId = $workflow->id();

// Later, load and check status
$workflow = WorkflowStub::load($workflowId);

if ($workflow->running()) {
    echo "Order is being processed...";
}

// Query current state
$status = $workflow->getStatus(); // Calls query method

// Send a signal
$workflow->cancelOrder(); // Calls signal method

// Check if completed
if ($workflow->completed()) {
    $result = $workflow->output();
    echo "Order completed: " . json_encode($result);
}

// Handle failures
if ($workflow->failed()) {
    $exceptions = $workflow->exceptions();
    foreach ($exceptions as $exception) {
        Log::error('Workflow failed', [
            'workflow_id' => $workflowId,
            'error' => $exception,
        ]);
    }
}

Build docs developers (and LLMs) love