intelfric / n8n-php-automation
A visual automation engine for Laravel, similar to n8n, Zapier, or Huginn
Installs: 1
Dependents: 0
Suggesters: 0
Security: 0
Stars: 0
Watchers: 0
Forks: 0
Open Issues: 0
pkg:composer/intelfric/n8n-php-automation
Requires
- php: ^8.2
- illuminate/console: ^10.0|^11.0|^12.0
- illuminate/database: ^10.0|^11.0|^12.0
- illuminate/support: ^10.0|^11.0|^12.0
- laravel/framework: ^10.0|^11.0|^12.0
Requires (Dev)
- orchestra/testbench: ^8.0|^9.0|^10.0
- phpunit/phpunit: ^10.0|^11.0
This package is not auto-updated.
Last update: 2025-12-26 12:24:37 UTC
README
A powerful visual automation engine for Laravel, similar to n8n, Zapier, or Huginn. Create, connect, and execute workflows made of modular nodes (triggers, actions, conditions) directly within your Laravel projects.
Features
- 🧩 Modular Architecture: Build workflows with reusable, composable nodes
- ⚡ Flow Execution Engine: Automatically resolves node dependencies and execution order
- 📊 Execution Logging: Track all flow executions with detailed logs
- 🔌 Built-in Nodes: HTTP requests, emails, delays, conditions, database queries
- 🎨 Extensible: Easy to create and register custom nodes
- 🚀 RESTful API: Full API for managing flows, nodes, and connections
- 📝 Event System: Hook into flow lifecycle with Laravel events
- ⚙️ Queue Support: Run flows asynchronously (optional)
Requirements
- PHP 8.2 or higher
- Laravel 10.x, 11.x, or 12.x
Installation
Install the package via Composer:
composer require intelfric/n8n-php-automation
Publish the configuration file:
php artisan vendor:publish --tag=automation-config
Publish and run the migrations:
php artisan vendor:publish --tag=automation-migrations php artisan migrate
Quick Start
1. Create a Flow
use DrMsigwa\Automation\Models\Flow; use DrMsigwa\Automation\Nodes\HttpRequestNode; use DrMsigwa\Automation\Nodes\EmailNode; // Create a new flow $flow = Flow::create([ 'name' => 'Send Weather Alert', 'description' => 'Fetch weather data and send email alert', 'status' => 'active', ]); // Add nodes to the flow $httpNode = $flow->nodes()->create([ 'type' => HttpRequestNode::class, 'name' => 'Fetch Weather', 'config' => [ 'method' => 'GET', 'url' => 'https://api.weather.com/current', ], ]); $emailNode = $flow->nodes()->create([ 'type' => EmailNode::class, 'name' => 'Send Alert', 'config' => [ 'to' => 'user@example.com', 'subject' => 'Weather Update', 'body' => 'Current weather: {{http_body}}', ], ]); // Connect nodes $flow->connections()->create([ 'source_node_id' => $httpNode->id, 'target_node_id' => $emailNode->id, ]);
2. Execute the Flow
use DrMsigwa\Automation\Engine\FlowRunner; $runner = new FlowRunner($flow); $result = $runner->run(['city' => 'New York']); dd($result);
Or via Artisan command:
php artisan automation:run 1
php artisan automation:run 1 --data='{"city":"New York"}'
3. Use the API
The package provides RESTful API endpoints:
# List all flows GET /api/automation/flows # Get a specific flow GET /api/automation/flows/{id} # Create a flow POST /api/automation/flows # Execute a flow POST /api/automation/flows/{id}/execute # Get available nodes GET /api/automation/available-nodes
Built-in Nodes
HTTP Request Node
Makes HTTP requests to external APIs.
[
'type' => HttpRequestNode::class,
'config' => [
'method' => 'POST',
'url' => 'https://api.example.com/data',
'headers' => ['Authorization' => 'Bearer token'],
'body' => ['key' => 'value'],
'timeout' => 30,
],
]
Email Node
Sends emails using Laravel's Mail system.
[
'type' => EmailNode::class,
'config' => [
'to' => 'recipient@example.com',
'subject' => 'Hello World',
'body' => 'Email content here',
'from' => 'sender@example.com', // optional
],
]
Delay Node
Adds delays between tasks.
[
'type' => DelayNode::class,
'config' => [
'seconds' => 5,
],
]
Condition Node
Evaluates conditional logic.
[
'type' => ConditionNode::class,
'config' => [
'left' => '{{http_status}}',
'operator' => '==',
'right' => 200,
],
]
Supported operators: ==, ===, !=, !==, >, >=, <, <=, contains, starts_with, ends_with, in
Database Query Node
Executes database queries using Laravel's Query Builder.
[
'type' => DatabaseQueryNode::class,
'config' => [
'table' => 'users',
'operation' => 'select',
'conditions' => [
['column' => 'status', 'operator' => '=', 'value' => 'active'],
],
'fields' => ['id', 'name', 'email'],
'limit' => 10,
],
]
Creating Custom Nodes
Create a new node by implementing the NodeInterface:
<?php namespace App\Automation\Nodes; use DrMsigwa\Automation\Contracts\NodeInterface; class SlackNotificationNode implements NodeInterface { public function execute(array $data): array { $config = $data['config'] ?? []; $message = $config['message'] ?? ''; // Your implementation here // Send message to Slack return [ 'slack_message_sent' => true, 'slack_timestamp' => now()->toISOString(), ]; } public function getDescription(): array { return [ 'name' => 'Slack Notification', 'description' => 'Sends notifications to Slack', 'icon' => 'message-square', 'category' => 'notification', 'inputs' => [ ['name' => 'message', 'type' => 'string', 'required' => true], ['name' => 'channel', 'type' => 'string', 'default' => '#general'], ], 'outputs' => [ ['name' => 'slack_message_sent', 'type' => 'boolean'], ['name' => 'slack_timestamp', 'type' => 'string'], ], ]; } }
Register your custom node in config/automation.php:
'nodes' => [ // Built-in nodes \DrMsigwa\Automation\Nodes\HttpRequestNode::class, \DrMsigwa\Automation\Nodes\EmailNode::class, // ... others // Your custom nodes \App\Automation\Nodes\SlackNotificationNode::class, ],
Or register dynamically using the facade:
use DrMsigwa\Automation\Facades\Automation; Automation::register(\App\Automation\Nodes\SlackNotificationNode::class);
Variable Substitution
Use double curly braces {{variable}} to reference data from previous nodes:
$emailNode = $flow->nodes()->create([ 'type' => EmailNode::class, 'config' => [ 'to' => '{{user_email}}', 'subject' => 'Order #{{order_id}} Confirmed', 'body' => 'Thank you {{user_name}}! Your order status: {{http_status}}', ], ]);
Events
Listen to flow lifecycle events:
// In your EventServiceProvider protected $listen = [ \DrMsigwa\Automation\Events\FlowStarted::class => [ \App\Listeners\LogFlowStart::class, ], \DrMsigwa\Automation\Events\NodeExecuted::class => [ \App\Listeners\LogNodeExecution::class, ], \DrMsigwa\Automation\Events\FlowCompleted::class => [ \App\Listeners\NotifyFlowCompletion::class, ], ];
Queue Support
Enable async flow execution in config/automation.php:
'queue' => [ 'enabled' => true, 'connection' => 'redis', 'queue' => 'automation', ],
Flow Execution Model
How Flows Execute
Important: Flows do NOT run endlessly or continuously by default. Each flow execution is:
- ✅ One-time: Runs once from start to finish
- ✅ Linear: Executes nodes sequentially in dependency order
- ✅ Finite: Completes after all nodes are executed
- ✅ Manual trigger required: Must be explicitly started each time
Triggering Flow Execution
Flows can be triggered in three ways:
1. Via Artisan Command
php artisan automation:run {flow_id}
php artisan automation:run 1 --data='{"user_id":123}'
2. Via API
POST /api/automation/flows/{id}/execute
3. Programmatically
use DrMsigwa\Automation\Engine\FlowRunner; use DrMsigwa\Automation\Models\Flow; $flow = Flow::find(1); $runner = new FlowRunner($flow); $result = $runner->run(['key' => 'value']);
Setting Up Continuous/Scheduled Execution
To run flows automatically on a schedule, use Laravel's Task Scheduler:
Option 1: Schedule Specific Flow
In app/Console/Kernel.php:
use DrMsigwa\Automation\Models\Flow; use DrMsigwa\Automation\Engine\FlowRunner; protected function schedule(Schedule $schedule) { // Run a specific flow every minute $schedule->call(function () { $flow = Flow::find(1); (new FlowRunner($flow))->run(); })->everyMinute(); // Run daily at midnight $schedule->call(function () { $flow = Flow::find(2); (new FlowRunner($flow))->run(); })->daily(); // Run every hour $schedule->call(function () { $flow = Flow::find(3); (new FlowRunner($flow))->run(); })->hourly(); }
Option 2: Run All Active Flows on Schedule
protected function schedule(Schedule $schedule) { $schedule->call(function () { $activeFlows = Flow::where('status', 'active')->get(); foreach ($activeFlows as $flow) { try { (new FlowRunner($flow))->run(); } catch (\Exception $e) { \Log::error("Flow {$flow->id} failed: " . $e->getMessage()); } } })->everyFiveMinutes(); }
Option 3: Using Queued Jobs for Better Performance
Create a job:
<?php namespace App\Jobs; use DrMsigwa\Automation\Models\Flow; use DrMsigwa\Automation\Engine\FlowRunner; use Illuminate\Bus\Queueable; use Illuminate\Contracts\Queue\ShouldQueue; use Illuminate\Foundation\Bus\Dispatchable; use Illuminate\Queue\InteractsWithQueue; class ExecuteFlowJob implements ShouldQueue { use Dispatchable, InteractsWithQueue, Queueable; public function __construct(public int $flowId, public array $data = []) { } public function handle() { $flow = Flow::find($this->flowId); if ($flow) { (new FlowRunner($flow))->run($this->data); } } }
Then schedule it:
protected function schedule(Schedule $schedule) { $schedule->job(new ExecuteFlowJob(1))->everyMinute(); }
Don't forget to run the Laravel scheduler:
# Add this to your crontab (cron on Linux/Mac) * * * * * cd /path-to-your-project && php artisan schedule:run >> /dev/null 2>&1
Webhook Triggers
For event-driven flows, use webhooks to trigger executions:
// In your routes/api.php or controller Route::post('/webhook/trigger-flow/{flowId}', function ($flowId) { $flow = Flow::find($flowId); if (!$flow) { return response()->json(['error' => 'Flow not found'], 404); } $data = request()->all(); $runner = new FlowRunner($flow); $result = $runner->run($data); return response()->json(['success' => true, 'result' => $result]); });
Loop Node Behavior
The LoopNode iterates through collections but has built-in safety limits:
[
'type' => LoopNode::class,
'config' => [
'items' => [1, 2, 3, 4, 5],
'max_iterations' => 1000, // Safety limit (default: 1000)
],
]
- Loops through finite collections only
- Maximum 1000 iterations by default
- Does NOT create infinite loops
Configuration
The package configuration file (config/automation.php) allows you to:
- Register custom nodes
- Configure queue settings
- Set execution timeouts
- Enable/disable API routes
- Customize route prefixes and middleware
Testing
Run the test suite:
composer test
Architecture
Core Components
| Component | Description |
|---|---|
| Flow | Represents a complete workflow |
| Node | Individual building block (trigger, condition, or action) |
| Connection | Defines data flow between nodes |
| FlowRunner | Orchestrates node execution and data passing |
| NodeRegistry | Handles node discovery and instantiation |
| ExecutionLogger | Logs all flow executions for tracking |
Database Schema
-- flows table id | name | description | status | created_at | updated_at -- nodes table id | flow_id | type | name | config (json) | position_x | position_y -- connections table id | flow_id | source_node_id | source_output | target_node_id | target_input -- executions table id | flow_id | status | started_at | finished_at | logs (json)
Advanced Usage
Programmatic Flow Execution
use DrMsigwa\Automation\Models\Flow; use DrMsigwa\Automation\Engine\FlowRunner; $flow = Flow::find(1); $runner = new FlowRunner($flow); try { $result = $runner->run([ 'user_id' => 123, 'action' => 'purchase', ]); $execution = $runner->getExecution(); $logger = $runner->getLogger(); echo "Execution ID: {$execution->id}\n"; echo "Status: {$execution->status}\n"; } catch (\Exception $e) { echo "Flow failed: " . $e->getMessage(); }
Accessing Execution Logs
use DrMsigwa\Automation\Models\Execution; $execution = Execution::find(1); foreach ($execution->logs as $log) { echo "[{$log['level']}] {$log['message']}\n"; }
Conditional Flow Execution
// Only execute flows with specific status $activeFlows = Flow::where('status', 'active')->get(); foreach ($activeFlows as $flow) { $runner = new FlowRunner($flow); $runner->run(); }
Roadmap
- Visual flow builder UI (Vue/React + Inertia.js or Livewire)
- Trigger nodes (webhooks, scheduled tasks, database events)
- Loop and iteration nodes
- Error handling and retry mechanisms
- Flow versioning
- Import/export flows as JSON
- Metrics and analytics dashboard
Contributing
Contributions are welcome! Please feel free to submit a Pull Request.
Security
If you discover any security-related issues, please email constantinomsigwa@intelfric.com instead of using the issue tracker.
License
The MIT License (MIT). Please see License File for more information.
Credits
- Dr.Msigwa constantinomsigwa@intelfric.com
- intelfric technology www.intelfric.com
- Inspired by n8n, Zapier, and Huginn
Support
- Documentation: https://github.com/INTELFRIC/n8n-php-automation
- Issues: https://github.com/INTELFRIC/n8n-php-automation/issues
Made with ❤️ for the Laravel community