Overview

DBFlow is a model-first workflow engine for Laravel and Filament. It attaches approvals, tasks, reject paths, and audit logs directly to your Eloquent models.

This documentation covers DBFlow Core (dbflowlabs/core), DBFlow Filament Standard (dbflowlabs/filament), and notes where DBFlow Pro (dbflowlabs/filament-pro) applies.

Alpha notice: Pin exact package tags for production. dbflowlabs/core and dbflowlabs/filament are published on Packagist; path or VCS repositories remain valid for local package development.

Learning path

If you are new to DBFlow, follow these pages in order:

  1. Try the live demo — explore approval flows without a local install (optional)
  2. What is DBFlow? — positioning, use cases, product layers
  3. Installation — requirements, Composer install, migrations, config
  4. Host Integration Checklist — register, sync, assignees, guards (required before start() works)
  5. Build Your First Workflow — a refund approval walkthrough based on the live demo
  6. Eloquent Models — model-first design and trait usage
  7. Code-defined Workflows — JSON definitions, providers, and sync
  8. Approve and Reject — task handling, reject strategies, audit logs

After the basics

Filament and examples

Reference

  • Architecture — DAG execution, concurrency model, hooks, user resolver
  • Pricing — Core, Pro Standard, Pro Ultimate editions

Quick reference

Requirements: PHP 8.3+, Laravel 13+, Composer 2+

Install:

composer require dbflowlabs/core
php artisan vendor:publish --tag=dbflow-config
php artisan vendor:publish --tag=dbflow-migrations
php artisan migrate

Register, sync, then start (see Host Integration):

use DbflowLabs\Core\Actions\SyncWorkflowDefinitions;
use DbflowLabs\Core\DBFlow;
use DbflowLabs\Core\Services\WorkflowDefinitionRegistry;

// In a service provider boot() method:
DBFlow::registerDefinitionProvider(
    app(WorkflowDefinitionRegistry::class),
    new RefundDisputeWorkflowProvider(),
);

app(SyncWorkflowDefinitions::class)->handle();

Attach to a model:

use DbflowLabs\Core\Contracts\Workflowable;
use DbflowLabs\Core\Contracts\WorkflowContextInterface;
use DbflowLabs\Core\Traits\HasWorkflow;
use Illuminate\Database\Eloquent\Model;

class RefundDispute extends Model implements Workflowable, WorkflowContextInterface
{
    use HasWorkflow;

    public function workflowBusinessKey(): ?string
    {
        return $this->reference_code;
    }

    public function workflowDisplayName(): string
    {
        return (string) $this->reference_code;
    }

    public function getWorkflowVariables(): array
    {
        return ['refund_amount' => (float) $this->refund_amount];
    }
}

Start, approve, reject (always pass the authenticated user as actor):

use DbflowLabs\Core\DBFlow;
use DbflowLabs\Core\Enums\RejectStrategy;
use DbflowLabs\Core\Enums\WorkflowTaskStatus;

DBFlow::start('refund_dispute_approval', $dispute, $user);

$task = $dispute->runningWorkflowInstance('refund_dispute_approval')
    ?->tasks()
    ->where('status', WorkflowTaskStatus::Pending)
    ->first();

DBFlow::approve($task, $user, 'Approved.');
DBFlow::reject($task, $user, 'Missing receipt.', RejectStrategy::Starter);

Optional Filament Standard package (separate from Core):

use DbflowLabs\Filament\Support\DBFlowFilamentPanel;

return DBFlowFilamentPanel::register($panel);
Something wrong? Open an issue on GitHub