Extending Workflowable
Workflowable is designed to be extended at multiple points.
Custom Step Types
Create your own step types for domain-specific logic by implementing the StepType interface. See the full Custom Step Types documentation for a complete guide with examples, the interface reference, and registration instructions.
Custom Action Handlers
For simpler cases where you just need to run some business logic within an action step, register action handlers instead of creating full step types.
Via Config
// In config/workflowable.php
'actions' => [
'send_slack_notification' => \App\Actions\SendSlackNotification::class,
],Handler Class
use Workflowable\Workflowable\Engine\ExecutionContext;
class SendSlackNotification
{
public function handle(ExecutionContext $context): array
{
$message = $context->getVariable('notification_message');
Slack::send($message);
return ['slack_sent' => true];
}
}Via Service Provider
use Workflowable\Workflowable\Registries\ActionRegistry;
public function boot(): void
{
$registry = app(ActionRegistry::class);
$registry->register('send_slack', SendSlackNotification::class);
}Action handlers are used with the built-in Action step type and don't require implementing the StepType interface. See the action docs for the full handler resolution order and dependency injection details.
Declaring Parameters
Action handlers can declare what configuration they accept by implementing DefinesParameters. This makes the action self-describing for workflow builders:
use Workflowable\Workflowable\Contracts\DefinesParameters;
use Workflowable\Workflowable\Support\Parameters\TextParameter;
use Workflowable\Workflowable\Support\Parameters\SelectParameter;
class SendSlackNotification implements DefinesParameters
{
public static function parameters(): array
{
return [
SelectParameter::make('channel', 'Slack Channel')
->options([
'general' => '#general',
'alerts' => '#alerts',
'engineering' => '#engineering',
]),
TextParameter::make('message_prefix', 'Message Prefix')
->optional()
->default('[Workflow]'),
];
}
public function handle(ExecutionContext $context): array
{
$channel = $context->getStepConfig('channel', 'general');
$prefix = $context->getStepConfig('message_prefix', '[Workflow]');
$message = $context->getVariable('notification_message');
Slack::to($channel)->send("{$prefix} {$message}");
return ['slack_sent' => true];
}
}See the Action Parameters documentation for the full list of parameter types and builder methods.
Event Listeners
React to workflow lifecycle events for notifications, logging, and integrations. See the Events Reference for the full event list and examples.
use Workflowable\Workflowable\Events\WorkflowCompleted;
Event::listen(WorkflowCompleted::class, function ($event) {
Log::info("Workflow completed: {$event->instance->id}");
});