Documentation

Complete guide to building flexible approval workflows in your Laravel application.

πŸ‡°πŸ‡­ Stand with Cambodia β€’ αž€αž˜αŸ’αž–αž»αž‡αžΆ

πŸ•ŠοΈ Cambodia Needs Peace πŸ•ŠοΈ

With heavy hearts, we stand with our brave soldiers defending Cambodia's land and dignity.
We seek no conflictβ€”only peace, justice, and respect for our sovereignty.

πŸ™ αž€αž˜αŸ’αž–αž»αž‡αžΆαžαŸ’αžšαžΌαžœαž€αžΆαžšαžŸαž“αŸ’αžαž·αž—αžΆαž– β€’ Together to protect Cambodia's sovereignty.

What is Laravel Approval Workflow?

A flexible, domain-driven approval workflow engine designed for enterprise Laravel applications. Build multi-step approval processes with role-based assignments, SLA tracking, and comprehensive audit trails.

Features

  • Multiple Workflow Versions: Define and evolve workflows over time without breaking existing instances
  • Dynamic Assignment: Assign tasks to users, roles (Spatie Permission integration), or managers
  • Flexible Modes: Support for 'any' (one person approves) or 'all' (consensus required) modes
  • SLA Monitoring: Built-in support for task deadlines and breach recording
  • Delegation: Automatic redirection of tasks based on user availability (vacation/out-of-office)
  • Audit Trail: Detailed event logging (started, assigned, acted, breached, completed) for every action
  • Conditional Transitions: Override default flow based on actions (approve/reject/changes_requested)
  • Team / Department Scoping: Optionally scope workflows, tasks, and approvers by team_id
  • UI & API Agnostic: No controllers, routes, views, or APIs are enforced. Each application decides how workflows are exposed

Installation

Requirements

  • PHP 8.2 or higher (PHP 8.4+ recommended)
  • Laravel 12.x
  • Composer
  • Spatie Laravel Permission (optional, for role-based assignment)

Step 1: Install via Composer

composer require putheakhem/approval-workflow

Step 2: Publish Configuration

php artisan vendor:publish --tag=approval-workflow-config

This publishes the configuration file to config/approval-workflow.php

Step 3: Publish Migrations

php artisan vendor:publish --tag=approval-workflow-migrations

Step 4: Run Migrations

php artisan migrate

Configuration

The configuration file is published to config/approval-workflow.php

return [
    // Enable SLA checking command
    'sla_command' => env('APPROVAL_WORKFLOW_SLA_COMMAND', false),
    
    // Default SLA hours for approval steps
    'default_sla_hours' => 24,
    
    // Team scoping
    'enable_team_scoping' => true,
];

Basic Usage

Make a Model Approvable

Use the HasWorkflow trait on any Eloquent model:

use PutheaKhem\ApprovalWorkflow\Concerns\HasWorkflow;

class Term extends Model
{
    use HasWorkflow;
}

⚠️ What This Package Does Not Do

  • Controllers or API routes
  • UI or view components
  • Notification delivery

These concerns are intentionally handled by the consuming application.

Workflow Definitions

Define workflows using PHP arrays or JSON format with versioning support:

[
    'steps' => [
        ['key' => 'start', 'type' => 'start', 'next' => 'review'],
        [
            'key' => 'review',
            'type' => 'approval',
            'mode' => 'any',
            'sla_hours' => 24,
            'assignment' => [
                'type' => 'role',
                'roles' => ['reviewer'],
            ],
            'next' => 'end',
        ],
        ['key' => 'end', 'type' => 'end'],
    ],
    'transitions' => [
        ['from' => 'review', 'on' => 'reject', 'to' => 'end'],
    ],
]

Starting Workflows

Initialize a workflow instance for your subject model:

$instance = $service->startWorkflow(
    workflowKey: 'service-approval',
    context: [
        'team_id' => 1,
        'requester_id' => auth()->id(),
    ],
    teamId: 1,
    startedBy: auth()->id(),
);

Approving & Rejecting Tasks

Approve

use PutheaKhem\ApprovalWorkflow\Services\ApprovalService;

$approval = app(ApprovalService::class);

$approval->approve(
    instance: $instance,
    taskId: $taskId,
    userId: auth()->id(),
    notes: 'Approved with conditions'
);

Reject

$approval->reject(
    instance: $instance,
    taskId: $taskId,
    userId: auth()->id(),
    notes: 'Missing required documents'
);

Request Changes

$approval->requestChanges(
    instance: $instance,
    taskId: $taskId,
    userId: auth()->id(),
    notes: 'Please provide additional details'
);

API Reference

Complete list of available services and methods.

WorkflowEngine::start()

Public

Starts a new workflow instance for the given subject.

Parameters
$subject β€’ Model β€’ Eloquent model to attach workflow
$workflowKey β€’ string β€’ Workflow definition key
$context β€’ array β€’ Workflow context data
$teamId β€’ ?int β€’ Team ID for scoping
$startedBy β€’ ?int β€’ User ID who started workflow
Returns: WorkflowInstance

ApprovalService::approve()

Public

Approves a workflow task.

Parameters
$instance β€’ WorkflowInstance β€’ Workflow instance
$taskId β€’ int β€’ Task ID to approve
$userId β€’ int β€’ User ID performing approval
$notes β€’ ?string β€’ Optional approval notes
Returns: void

ApprovalService::reject()

Public

Rejects a workflow task.

Parameters
$instance β€’ WorkflowInstance β€’ Workflow instance
$taskId β€’ int β€’ Task ID to reject
$userId β€’ int β€’ User ID performing rejection
$notes β€’ ?string β€’ Optional rejection notes
Returns: void

ApprovalService::requestChanges()

Public

Requests changes on a workflow task.

Parameters
$instance β€’ WorkflowInstance β€’ Workflow instance
$taskId β€’ int β€’ Task ID for change request
$userId β€’ int β€’ User ID requesting changes
$notes β€’ ?string β€’ Required change description
Returns: void

DelegationService::delegate()

Public

Delegates approval authority to another user.

Parameters
$fromUserId β€’ int β€’ Delegating user ID
$toUserId β€’ int β€’ Delegate user ID
$validFrom β€’ Carbon β€’ Delegation start date
$validUntil β€’ Carbon β€’ Delegation end date
Returns: Delegation

Events

The package emits the following domain events:

  • WorkflowStarted

    Fired when a workflow instance is created

  • TaskAssigned

    Fired when a task is assigned to users

  • TaskApproved

    Fired when a task is approved

  • TaskRejected

    Fired when a task is rejected

  • WorkflowCompleted

    Fired when a workflow completes

  • SlaBreached

    Fired when SLA deadline is exceeded

Audit Trail

All workflow actions are recorded in the workflow_events table for transparency and compliance.

Event Types

  • workflow_started
  • task_created
  • task_assigned
  • assignee_acted
  • task_finished
  • workflow_completed
  • sla_breached

SLA Support

Enable SLA checking to monitor approval deadlines.

Enable SLA Command

APPROVAL_WORKFLOW_SLA_COMMAND=true

Run SLA Check

php artisan workflow:check-sla

Schedule in Kernel

// In routes/console.php or app/Console/Kernel.php
Schedule::command('workflow:check-sla')->hourly();