Weave Code
Weaver
Helps Laravel developers discover, compare, and choose open-source packages. See popularity, security, maintainers, and scores at a glance to make better decisions.
Feedback
Share your thoughts, report bugs, or suggest improvements.
Subject
Message

Workflows Laravel Package

the42coders/workflows

The42Coders Workflows lets you design and run database-driven workflows in Laravel through a visual editor. Build processes from start nodes, tasks, conditions, and more, then attach them to Eloquent models with a simple API—great for approvals, onboarding, and business process automation.

View on GitHub
Deep Wiki
Context7

Getting Started

composer require the42coders/workflows
php artisan vendor:publish --tag=workflows
php artisan migrate

Publish both the config and migrations tags (and the assets tag if you want the bundled drag-and-drop editor UI); the exact tag list is in the package's service provider, so run php artisan vendor:publish interactively once and note what it offers before scripting it in CI.

Where to look first, in order:

  1. config/workflows.php — the node-type registry. This is the heart of the package: it maps a string key (persisted on workflow_nodes.type) to a PHP class that does the work and an icon/colour for the editor. Everything you extend starts here.
  2. src/Models/Workflow.php, WorkflowNode.php, WorkflowRun.php — the persisted graph and the execution record. WorkflowRun is your audit log and your debugging surface.
  3. src/Nodes/ — the shipped node classes (mail, model update, condition, etc.). Read two or three before writing your own; they establish the expected method signatures and the convention for returning a value to the next node.
  4. The editor route registered by the package (typically behind web middleware at a /workflows prefix). Log in as an admin and drag a two-node flow before writing any code — it's the fastest way to understand how start_node_id, connections, and node config JSON fit together.

First real use case: "when an order is paid, email a receipt and flip the order status." Make the Order model use the package's HasWorkflows trait, create a workflow with a trigger node bound to Order, a mail node, and an update node, then kick it off from the payment webhook:

use 42coders\Workers\Workflows\Models\Workflow; // namespace per your install

Workflow::start($order);           // returns a WorkflowRun

If start() isn't on the facade in your version, the trait exposes the same entry point on the model. Confirm the call site against src/ before building on it — this is a small package and the public surface is thin enough to read in ten minutes.

Implementation Patterns

Treat nodes as thin adapters over jobs. The single most important pattern for day-to-day sanity: the node resolves its config into a payload and dispatches a queued job. Keep branching logic in the graph, not in the node. This means a slow SMTP send or a third-party API call never blocks the request that started the workflow, and a failed node retries under your normal queue policy instead of dying with the HTTP request.

class SendReceiptNode extends Node
{
    public function handle(): mixed
    {
        SendReceiptJob::dispatch($this->subject, $this->config('template'));
        return $this->subject;
    }
}

Start workflows from observers, not from controllers. One OrderObserver::paid() that calls start() is easier to audit than eight controllers each remembering to. Guard it so only one run exists per state transition — a paid_at that gets set twice on a retried webhook should not double-send receipts.

Use condition nodes as the only branch mechanism. Resist if statements inside action nodes; when someone asks "why didn't the refund email go out?", the answer needs to be visible in the graph, not buried in PHP. Converge branches back onto a shared node rather than duplicating downstream steps.

Version by copying. Editing a workflow that has live WorkflowRun rows means old runs replay against a graph that no longer matches what actually happened. Clone the workflow, edit the clone, repoint, and archive the original. Cheap, and it makes the audit log honest.

Integrate with the rest of the app through the subject, not through globals. Every node receives the model instance that started the run. Pass data forward by mutating the subject (status, timestamps) or by writing to your own domain tables — not by stuffing a shared array into the run record.

Test with fakes and assertions on the run. Queue::fake() plus Bus::fake() lets you assert that a workflow starting from a paid order dispatched the receipt job and flipped the status, without any SMTP. Assert on WorkflowRun rows (status, node log entries) for the graph shape, and on jobs for the side effects. Run one end-to-end test with the real queue on SQLite in-memory to catch serialisation problems.

Register custom nodes once, in config, with stable keys. The type string is persisted in the database forever. Name it after the domain concept (order.refund), never after the class name, so refactors don't orphan every existing workflow.

Gotchas and Tips

  • The package's last release is late 2023. Before committing, verify installability on your current Laravel and PHP versions in a throwaway branch. Expect to need "minimum-stability" tweaks, a fork, or a repositories vcs entry pointing at a patched fork. With zero dependents on Packagist there's no crowd verifying compatibility for you — you are the compatibility test.
  • Don't start a workflow inside an open transaction. If an order is created and the workflow fires before commit, nodes read stale or missing rows. Use DB::afterCommit() or dispatch a job from the observer so the run begins after the write lands.
  • Guard against loops. A graph with a back-edge will spin. Put a step counter in your node base class (or a max_steps check in the runner) and fail the run loudly rather than letting the queue chew through it.
  • Node config is unstructured JSON. There's no schema validation on what the editor stores. Validate every config key inside the node's handle(), with an explicit exception naming the node — a null template path three nodes deep is otherwise invisible.
  • Silent no-ops. A workflow with a missing or null start node simply does nothing when started. When "the automation didn't run," check workflow_runs first: no row means the start never fired (bad trait, wrong class, observer not registered); a row with a stuck node means the graph or config is wrong.
  • Gate the editor. The bundled UI is an admin tool; make sure its routes sit behind your auth middleware and an authorization gate. Anyone who can open the editor can wire an arbitrary node to an arbitrary model — treat it as equivalent to php artisan tinker access.
  • Publish the assets and check for Vite/Mix clashes. The editor ships its own JS/CSS; if your app uses Vite with a strict asset pipeline, the published files may need to be added to your build or served from public/vendor untouched.
  • Prune run history. WorkflowRun (and any per-node log table) grows monotonically and gets wide. Schedule a nightly delete of runs older than 30–90 days, keeping failures longer if you rely on them for incident review.
  • Re-run config:cache after registering a new node type, or the editor won't list it and existing nodes with that type will resolve to null on the next run.
  • Extension points worth knowing: custom node classes registered in config/workflows.php, a custom Blade view per node for its config form in the editor, and the model trait for attaching workflows to additional entities. Everything else — retries, idempotency, notifying humans on failure — is yours to build; the package gives you a graph runner and an audit table, not an operations story.
Weaver

How can I help you explore Laravel packages today?

Conversation history is not saved when not logged in.
Prompt
Add packages to context
No packages found.
pharaonic/laravel-notification-dependencies
beautinow/translug
dev-brainiac/bot-cloaked
octoberrain/html
octoberrain/extension
octoberrain/exception
octoberrain/contracts
frankyso/ipaymu
3mdikram/worldmoneywords
snowsoft/config
itmosoft/laravel-subscriptions
larva/laravel-ai-qwen
adachsoft/api-version-bundle
cgv/localized-resource
noith/settings
kda/laravel-package
kda/filament-dynamic-navigation
bypersoft/signbox
pairus/product-data
fayne/laravel-filament-cms-core