Skip to content

Plugin Integration ​

Voodflow provides a first-class API for third-party Laravel plugins and packages to expose their own events and models. This allows users to build workflows triggered by any plugin event — not just CRUD operations on core models.

There are three independent mechanisms, and you can use them together:

What you needMechanism
Expose a custom event in the trigger pickerVoodflow::registerEvent()
Let Voodflow read fields from your modelHasVoodflow interface or Voodflow::registerModelFields()
Control the exact payload sent to a workflowPayloadProvider interface
Customize the trigger identifier of an eventIdentifiableEvent interface

1. Registering a Custom Event ​

Call Voodflow::registerEvent() inside your plugin's ServiceProvider::boot() to make an event selectable in the Event Trigger node.

php
use Voodflow\Voodflow\Voodflow;

public function boot(): void
{
    Voodflow::registerEvent(
        eventClass: \Vendor\MyPlugin\Events\InvoicePaid::class,
        name:       'Invoice Paid',
        description: 'Fired when an invoice is marked as paid',
        group:      'MyPlugin',
    );

    Voodflow::registerEvent(
        eventClass: \Vendor\MyPlugin\Events\SubscriptionExpired::class,
        name:       'Subscription Expired',
        group:      'MyPlugin',
    );
}
ParameterTypeDescription
eventClassstringFully-qualified class name of the event
namestringHuman-readable label shown in the event picker
descriptionstring|nullOptional tooltip/description in the UI
groupstring|nullGroups events in the dropdown (e.g. "MyPlugin")

Events are standard Laravel events dispatched with event(). Voodflow listens for them automatically — there is nothing else to configure.

php
// Anywhere in your plugin:
event(new \Vendor\MyPlugin\Events\InvoicePaid($invoice));

2. Exposing Model Fields (HasVoodflow) ​

To let Voodflow read and map fields from your Eloquent model (e.g. for {{tags}} resolution in nodes), implement the HasVoodflow interface on the model:

php
use Voodflow\Voodflow\Contracts\HasVoodflow;

class Invoice extends Model implements HasVoodflow
{
    public static function getVoodflowFields(): array
    {
        return [
            'essential' => [
                'id'         => 'ID',
                'number'     => 'Invoice Number',
                'total'      => 'Total',
                'status'     => 'Status',
                'due_date'   => 'Due Date',
                'created_at' => 'Created At',
            ],
            'relations' => [
                'customer' => [
                    'fields' => [
                        'id'    => 'Customer ID',
                        'name'  => 'Customer Name',
                        'email' => 'Customer Email',
                    ],
                ],
                'items' => [
                    'fields' => [
                        'description' => 'Item Description',
                        'quantity'    => 'Quantity',
                        'unit_price'  => 'Unit Price',
                    ],
                ],
            ],
        ];
    }
}

Return value structure ​

KeyTypeDescription
essentialarrayFlat fields of this model. Key = field name, value = label.
relationsarrayOptional. Keyed by relation method name.
relations.*.fieldsarrayFields from the related model to expose.
relations.*.expandarrayNested relations to recursively expand.

Once HasVoodflow is implemented, Voodflow automatically discovers the model's fields when an event carrying that model instance is fired.


3. Registering Fields for Third-Party Models ​

If you cannot modify a model (e.g. it belongs to another package), use Voodflow::registerModelFields() in your ServiceProvider::boot():

php
use Voodflow\Voodflow\Voodflow;

public function boot(): void
{
    Voodflow::registerModelFields(
        modelClass: \SomeVendor\Package\Models\Order::class,
        fields: [
            'essential' => [
                'id'         => 'Order ID',
                'reference'  => 'Reference',
                'total'      => 'Total',
                'status'     => 'Status',
            ],
            'relations' => [
                'customer' => [
                    'fields' => ['name' => 'Name', 'email' => 'Email'],
                ],
            ],
        ],
        alias: 'order',   // Optional: key used in the payload (defaults to model name)
    );
}

The optional alias parameter controls the key under which the model data is nested in the workflow context. For example, with alias: 'order', templates use {{order.total}} instead of {{Order.total}}.


4. Controlling the Payload (PayloadProvider) ​

By default, Voodflow serializes the public properties of your event class using reflection. To take full control of what data the workflow receives, implement PayloadProvider on your event:

php
use Voodflow\Voodflow\Contracts\PayloadProvider;

class InvoicePaid implements PayloadProvider
{
    public function __construct(
        public readonly Invoice $invoice,
        public readonly string  $paidBy,
    ) {}

    public function toVoodflowPayload(): array
    {
        return [
            'invoice' => [
                'id'     => $this->invoice->id,
                'number' => $this->invoice->number,
                'total'  => $this->invoice->total,
                'status' => $this->invoice->status,
            ],
            'paid_by'    => $this->paidBy,
            'paid_at'    => now()->toIso8601String(),
        ];
    }
}

The array returned by toVoodflowPayload() becomes the root context of the workflow execution. All {{tags}} in downstream nodes resolve against this structure.


5. Customizing the Event Identifier (IdentifiableEvent) ​

By default, Voodflow uses the fully-qualified class name (FQCN) as the trigger identifier. If you want to use a stable, human-friendly string (for example to maintain compatibility across refactors), implement IdentifiableEvent:

php
use Voodflow\Voodflow\Contracts\IdentifiableEvent;

class InvoicePaid implements IdentifiableEvent
{
    public function voodflowEventIdentifier(): string
    {
        return 'myplugin.invoice.paid';
    }
}

Changing the identifier of an existing event will break any workflow triggers already pointing to the old identifier. Use this when first creating the event, not as a retroactive refactor.


Full Example ​

A typical plugin ServiceProvider integrating all mechanisms:

php
namespace Vendor\MyPlugin;

use Illuminate\Support\ServiceProvider;
use Voodflow\Voodflow\Voodflow;
use Vendor\MyPlugin\Events\InvoicePaid;
use Vendor\MyPlugin\Events\SubscriptionExpired;
use Vendor\MyPlugin\Models\Invoice;
use Vendor\MyPlugin\Models\Subscription;

class MyPluginServiceProvider extends ServiceProvider
{
    public function boot(): void
    {
        // Register events in the trigger picker
        Voodflow::registerEvent(
            eventClass: InvoicePaid::class,
            name: 'Invoice Paid',
            description: 'Fired when an invoice payment is confirmed',
            group: 'MyPlugin',
        );

        Voodflow::registerEvent(
            eventClass: SubscriptionExpired::class,
            name: 'Subscription Expired',
            group: 'MyPlugin',
        );

        // Expose model fields for tag resolution
        // (only needed if the models don't already implement HasVoodflow)
        Voodflow::registerModelFields(
            modelClass: Subscription::class,
            fields: [
                'essential' => [
                    'id'         => 'ID',
                    'plan'       => 'Plan',
                    'expires_at' => 'Expires At',
                ],
            ],
            alias: 'subscription',
        );
    }
}

Dispatch events from anywhere in your plugin as normal:

php
event(new InvoicePaid($invoice, auth()->id()));
event(new SubscriptionExpired($subscription));

Interface Summary ​

Interface / ClassNamespacePurpose
HasVoodflowVoodflow\Voodflow\ContractsDeclare field schema on a model
PayloadProviderVoodflow\Voodflow\ContractsReturn a custom payload array from an event
IdentifiableEventVoodflow\Voodflow\ContractsOverride the trigger identifier string
Voodflow::registerEvent()Voodflow\Voodflow\VoodflowRegister an event in the UI picker at runtime
Voodflow::registerModelFields()Voodflow\Voodflow\VoodflowRegister field schema for a third-party model

Voodflow Documentation.