Skip to main content
Of course! Building a workflow engine is a fascinating project. Here’s a comprehensive guide on how to create a simple, yet powerful, workflow graph engine using Laravel for the backend, Vue 3 for the frontend, Laravel’s Pipeline for execution, and an Artisan command for triggering.

High-Level Architecture

  1. Frontend (Vue 3): A visual editor where users can drag, drop, and connect nodes to define a workflow. We’ll use a library like Vue Flow for this. The state of the graph (nodes, edges, and their configurations) will be stored as a JSON object.
  2. Backend (Laravel API):
  • An API endpoint to save/load the workflow’s JSON definition to a database.
  • A Workflow model to represent the stored workflows.
  1. Execution Layer (Laravel Pipeline & Artisan):
  • An Artisan command (workflow:run) will trigger a specific workflow.
  • A Translator/Engine Service will parse the workflow’s JSON and translate it into a series of executable “Pipe” classes.
  • Laravel’s Pipeline will execute these pipes sequentially, passing a “state” object through each one, which nodes can read from and write to.
  • Branching Logic (Conditional/Switch): The standard Laravel Pipeline is linear. We’ll adapt our engine to handle branching by dynamically deciding the next node to execute based on the current state.

Step 1: Backend Setup (Laravel)

1.1. Create Project and Database Model

Open the generated migration file ..._create_workflows_table.php and define the schema.
Run the migration:

1.2. Set up the Workflow Model

In app/Models/Workflow.php, add a cast for the definition field.

1.3. Create the API Controller

Define the routes in routes/api.php.
Implement the controller logic.

Step 2: The Core Execution Engine

This is the heart of our system. It translates the visual graph into executable code.

2.1. Define the State Object

The “state” is an object that gets passed from one node to the next. Each node can read from it and write to it. A simple DataObject using ArrayAccess is perfect for this.

2.2. Create the Pipe Classes for Each Node Type

Create a directory app/Workflows/Pipes. Each class will represent a node type and have an handle method. a) DB Access Node
b) Custom Code Node
Security Warning: Using eval() is extremely dangerous if the code comes from untrusted users. In a real-world scenario, you should use a sandboxed environment or a pre-approved list of invokable classes. For this example, we’ll proceed with eval for simplicity.
Example code for this node: $state['fullName'] = $state['firstName'] . ' ' . $state['lastName']; c) Terminator Node This node will stop the pipeline and can format the final output.

2.3. The Workflow Engine Service (Handles Graph Traversal & Branching)

This service is the most crucial piece. It takes the workflow definition and executes it node by node.

Step 3: The Artisan Command

Implement the command to use our WorkflowEngine.

Step 4: Frontend Setup (Vue 3)

We’ll use Vue Flow to create the visual editor.

4.1. Install Vue and Dependencies

Configure vite.config.js and resources/js/app.js to use Vue.

4.2. Create the WorkflowEditor.vue Component

This component will contain the graph editor.
Custom Nodes for Configuration Vue Flow allows you to create custom nodes with forms to edit their configuration (data property). For a DB node, you would have inputs for Table, Operation, etc. This data is what gets passed as $config to your backend Pipe classes. Here is a simplified example of a custom DB node:
You would then register this in your main editor component to be used when type is db_access.

Step 5: Tying it all together

  1. Design a Workflow: Use your Vue frontend to create a workflow.
  • Add a Trigger node.
  • Add a DB Access node. Configure it to fetch a user: table: 'users', operation: 'first', where: [{field: 'id', operator: '=', value: 1}], outputKey: 'user'.
  • Add a Terminator node.
  • Connect Trigger -> DB Access -> Terminator.
  1. Save: Click “Save”. The Vue app sends a PUT request to /api/workflows/1 with a JSON payload like this:
  1. Run: Trigger the execution via an API call (e.g., from a button in your app) or directly via the command line.
  • Via CLI:
  • Via API: A POST request to http://your.app/api/workflows/1/run.
  1. Execution Flow:
  • The RunWorkflow command starts.
  • It calls the WorkflowEngine.
  • The engine finds the trigger node and starts.
  • It moves to the db_access node (node-1). It executes DbAccessPipe with the configured data. The pipe runs DB::table('users')->where('id', 1)->first() and stores the result in $state['user'].
  • It moves to the terminator node (node-2), which ends the process and returns the final state.
  • The Artisan command prints the final state containing the user object.
This provides a solid foundation. You can now expand on it by creating more complex node types, adding better error handling, logging each run to a database, and building a more sophisticated UI for configuring nodes.

UI Wireframe

Of course! Here is a text-based wireframe that visualizes the Vue front-end for your workflow engine. This wireframe illustrates the key components and their interactions. We’ll visualize two states:
  1. The main editor view with a workflow loaded.
  2. The view when a specific node is selected, showing the contextual properties panel.

Wireframe 1: Main Editor View

This is the default view when a user opens a workflow to edit it.

Breakdown of the Main View:

  1. Header:
    • Workflow Engine: Application title.
    • [ My First Workflow ▼]: A dropdown to switch between existing workflows.
    • [ Save ]: Saves the current graph layout and node configurations to the Laravel backend.
    • [ Run Workflow ]: Triggers the Artisan command via the API, potentially opening a modal to ask for initial input data.
  2. Left Sidebar (WORKFLOWS):
    • A list of all saved workflows.
    • The > indicates the currently selected workflow being displayed on the canvas.
    • [+ New Workflow] button to create a new, empty workflow.
  3. Main Content Area:
    • NODE PALETTE: A toolbar with buttons for each available node type. Clicking one of these would add a new node of that type to the canvas.
    • ( C A N V A S ): The main area where the graph is built.
      • Nodes: Represented by boxes (+---+). Each has an icon, a type (Trigger, DB Access), and a user-defined label (Find User).
      • Edges: Represented by lines and arrows (--->) connecting the nodes.
      • Handles/Ports: The points on a node where edges connect. For branching nodes like If/Else, the outgoing edges are labeled (true, false).
  4. Footer:
    • Displays status messages like “Ready”, “Saving…”, “Workflow Saved”, or “Execution Failed”.

Wireframe 2: Node Properties Panel (Contextual)

This view shows what happens when the user clicks on the “🗃️ DB Access (Find User)” node on the canvas. The right sidebar appears to show its specific configuration.

Breakdown of the Properties View:

  1. Canvas Interaction:
    • The selected node, DB Access (Find User), is highlighted (represented by +===============+).
  2. Right Sidebar (PROPERTIES):
    • This panel is contextual. Its content changes based on the selected node’s type.
    • Node Label: A generic field for all nodes to give them a descriptive name.
    • Table Name: An input field specific to the DB Access node.
    • Operation: A dropdown (<...▼>) to select the database action (first, get, insert, etc.).
    • Output Key: The variable name under which the result of this node will be stored in the workflow’s State object (e.g., state['found_user']).
    • Conditions: A dynamic form to build the WHERE clause. The user can add multiple conditions. This demonstrates how complex data for a node’s configuration can be captured.
      • It shows how values can be hardcoded (1) or pulled from the workflow state (input_email), making the nodes dynamic.
    • [+ Add]: A button to add another WHERE condition row.
This text-based wireframe provides a clear blueprint for what you need to build in Vue, showing the overall layout, the components, their states, and how they interact to create a functional workflow editor.

Vue2 Vertical Flow

Absolutely! A vertically flowing workflow is a fantastic way to simplify the UI, and it’s perfectly achievable in Vue 2 without the need for a complex graph library. This approach is often more intuitive for users who are used to step-by-step processes. Instead of a free-form canvas, we’ll build an interface that resembles a structured list, where branching is handled through indentation.

Text-Based Wireframe: Vertical Workflow Editor

This wireframe shows a workflow for processing a new user signup. It includes a conditional branch.

How to Build This in Vue 2

This design is much simpler to implement as it doesn’t require drag-and-drop or position management. It’s essentially a recursive list of components.

1. The Data Structure (JSON)

The visual structure above maps beautifully to a nested array of objects. This is the JSON you’ll save to your Laravel backend.

2. Vue 2 Component Structure

You would primarily need two recursive components. WorkflowEditor.vue (The Parent)
WorkflowStep.vue (The Recursive Child) This component renders a single step and, if it’s a conditional, recursively renders more WorkflowStep components for its branches.

3. Backend Engine Adaptation

Your Laravel WorkflowEngine would also be simplified. Instead of traversing edges, you would recursively execute the arrays.
This vertical approach is an excellent starting point. It’s robust, easy for users to understand, and simplifies both the frontend and backend logic significantly.