Skip to content

PHP Code

Type key: php_code_node
Group: Utilities
Category: utility
Tier: CORE

The PHP Code node executes arbitrary PHP code inside a sandboxed closure. It provides direct access to the current $input data array and the $context (ExecutionContext), making it the most powerful and flexible node for custom logic that cannot be expressed through the standard node library.

Handles

HandleDirectionDescription
inputInputData passed as $input inside the code closure
outputOutputEmits whatever value is returned by the return statement

Configuration

FieldTypeDefaultDescription
codestringreturn $input;PHP code string to execute; <?php tag is stripped automatically
output_fieldsarray[]Optional list of field names to extract from the return value; if empty, the full return value is emitted

Execution Environment

The code is executed inside a PHP closure, providing access to:

VariableTypeDescription
$inputarrayThe incoming data array
$contextExecutionContextFull execution context (variables, credentials, run metadata)

The closure signature is:

php
$fn = function (array $input, ExecutionContext $context) {
    // your code here
    return $result;
};

The return statement value becomes the node's output. Any PHP type is accepted: array, string, int, bool, or null.

Code Preprocessing

Before execution, the engine:

  1. Strips a leading <?php tag if present
  2. Wraps the code in a closure that binds $input and $context
  3. Evaluates the closure with eval()
  4. Catches any Throwable and returns ExecutionResult::failure() with the exception message

Context API

Inside the code, $context exposes:

php
// Read a workflow variable
$tenantId = $context->getVariable('tenant_id');

// Set a workflow variable
$context->setVariable('processed_count', 42);

// Access execution metadata
$runId    = $context->executionId;
$workflow = $context->workflow;

// Access credentials (returns a CredentialProxy)
// Use ->execute() with an action such as 'get_auth_headers', 'get_api_client', etc.
$credential = $context->getCredential('my_api_credential');
$headers    = $credential->execute('get_auth_headers');

Examples

Passthrough (Default)

php
return $input;

Data Transformation

php
return [
    'full_name'   => $input['first_name'] . ' ' . $input['last_name'],
    'email_lower' => strtolower($input['email']),
    'age'         => (int) $input['age'],
    'is_adult'    => (int) $input['age'] >= 18,
];

Conditional Logic

php
$discount = 0;

if ($input['total'] > 500) {
    $discount = 0.15;
} elseif ($input['total'] > 100) {
    $discount = 0.05;
}

return array_merge($input, [
    'discount_rate'   => $discount,
    'discounted_total' => round($input['total'] * (1 - $discount), 2),
]);

Using Laravel Helpers

php
use Illuminate\Support\Str;

return [
    'slug'      => Str::slug($input['title']),
    'uuid'      => Str::uuid()->toString(),
    'excerpt'   => Str::limit($input['body'], 160),
    'timestamp' => now()->toIso8601String(),
];

Calling an Eloquent Model

php
$user = \App\Models\User::find($input['user_id']);

if (! $user) {
    return ['found' => false];
}

return [
    'found'    => true,
    'name'     => $user->name,
    'plan'     => $user->subscription?->plan,
    'is_admin' => $user->hasRole('admin'),
];

HTTP Request with Guzzle

php
$credential = $context->getCredential('openai');
$authHeaders = $credential->execute('get_auth_headers');

$response = \Illuminate\Support\Facades\Http::withHeaders($authHeaders)
    ->post('https://api.openai.com/v1/embeddings', [
        'model' => 'text-embedding-3-small',
        'input' => $input['text'],
    ]);

return $response->json();

Aggregate Calculation

php
$items = $input['items'] ?? [];

$subtotal = array_sum(array_column($items, 'price'));
$vat      = round($subtotal * 0.22, 2);

return [
    'items'    => $items,
    'subtotal' => $subtotal,
    'vat'      => $vat,
    'total'    => round($subtotal + $vat, 2),
];

output_fields Filtering

When output_fields is set, only the specified keys are emitted:

yaml
output_fields: [full_name, email_lower]

Given a return value of ['full_name' => 'John Doe', 'email_lower' => 'john@example.com', 'raw' => '...'], only full_name and email_lower will be forwarded downstream.

Error Handling

Any exception or fatal error thrown inside the code is caught by the engine:

php
throw new \RuntimeException("Custom error: {$input['id']} not processable");

The node emits ExecutionResult::failure() with:

  • error_message: The exception message
  • error_code: PHP_CODE_EXCEPTION

Use a Catch node to handle these failures.

Security Considerations

Warning: The PHP Code node executes arbitrary PHP via eval(). It should be accessible only to trusted administrators.

  • Restrict access using Filament Shield policies; do not expose it to end-users
  • Avoid storing sensitive credentials directly in code; use $context->getCredential() instead
  • In multi-tenant environments, ensure workflow editing is limited to trusted roles

Notes

  • The node is ideal for one-off transformations that would require multiple standard nodes to express
  • For recurring, complex logic, consider creating a Custom Node instead
  • eval() operates in the same PHP process and memory space — heavy operations can impact performance; offload to queues
  • All Laravel facades, Eloquent models, and helpers are available in scope

Proprietary software — source-available. All rights reserved.