PHP-ETL - Operations

Building Blocks - If

The IfConfig operation evaluates a Rule Engine condition against the item’s data and routes it to exactly one sub-chain based on the result — then when the condition is met, else (if configured) otherwise. Unlike Split, only one branch ever runs for a given item, so that branch is free to transform or replace the item; there’s no risk of conflicting modifications from branches running in parallel.

Key characteristics:

  • Evaluates a condition using a typed RuleConfigInterface or an Expression — same options as FilterDataConfig
  • Routes the item to exactly one of then / else — never both
  • The chosen branch can freely modify the item, since no other branch runs alongside it
  • else is optional — without it, a not-met condition just lets the item continue unchanged
  • Useful for branching logic within a single step, instead of filtering the item out entirely

Configuration

use Oliverde8\Component\PhpEtl\OperationConfig\IfConfig;
use Oliverde8\Component\PhpEtl\ChainConfig;
use Oliverde8\Component\RuleEngine\RuleConfig\GetRuleConfig;

$ifConfig = new IfConfig(
    then: $thenChainConfig,          // ChainConfig run when the condition evaluates truthy
    rules: new GetRuleConfig('IsSubscribed'), // Typed rule, evaluated against the item's data
    else: $elseChainConfig,           // Optional ChainConfig run otherwise
    negate: false,                     // Optional: invert the condition result
    isolateContext: false              // Optional: isolate the chosen branch's context from the parent
);

For a simple boolean condition, an Expression is often less verbose than a typed rule — a Symfony Expression Language string evaluated against data (the item’s data) and context (the execution context’s parameters):

use Oliverde8\Component\PhpEtl\Expression\Expression;

$ifConfig = new IfConfig(
    then: $thenChainConfig,
    rules: new Expression('data["Country"] == "US"'),
    else: $elseChainConfig,
);

Parameters:

  • then: A ChainConfig run when the condition evaluates truthy (or falsy, if negate is true)
  • rules: A RuleConfigInterface or an Expression — same options as FilterDataConfig. A plain array is also accepted but deprecated, see Legacy Array Syntax
  • else: An optional ChainConfig run otherwise. Without it, the item just continues to the next step unchanged
  • negate: Inverts the condition result. Default false
  • isolateContext: When true, the chosen branch runs against its own clone of the execution context instead of the parent’s. Default false

Isolating Context

By default, all branches share the same execution context as the main chain — a parameter set with $context->setParameter() inside one branch is visible in every other branch and in the main chain once the conditional is done. Pass isolateContext: true to give each branch its own independent copy instead:

$ifConfig = new IfConfig(
    // ...
    isolateContext: true
);

Branches can then no longer see each other’s context changes, and nothing leaks back to the main chain. The file system and logger stay shared — only context parameters are isolated.

See Execution Context for more.

Example: Different Handling for Subscribed Customers

use Oliverde8\Component\PhpEtl\ChainConfig;
use Oliverde8\Component\PhpEtl\OperationConfig\Extract\CsvExtractConfig;
use Oliverde8\Component\PhpEtl\OperationConfig\IfConfig;
use Oliverde8\Component\PhpEtl\OperationConfig\Transformer\RuleTransformConfig;
use Oliverde8\Component\PhpEtl\OperationConfig\Loader\CsvFileWriterConfig;
use Oliverde8\Component\RuleEngine\RuleConfig\GetRuleConfig;

$chainConfig = new ChainConfig();

$chainConfig
    ->addLink(new CsvExtractConfig())
    ->addLink(new IfConfig(
        rules: new GetRuleConfig('IsSubscribed'),
        then: (new ChainConfig())
            ->addLink((new RuleTransformConfig(false))
                ->addColumn('status', [['constant' => ['value' => 'subscribed']]])
            ),
        else: (new ChainConfig())
            ->addLink((new RuleTransformConfig(false))
                ->addColumn('status', [['constant' => ['value' => 'not-subscribed']]])
            )
    ))
    ->addLink(new CsvFileWriterConfig('customers-tagged.csv'));

Result: Every row continues to customers-tagged.csv, tagged subscribed or not-subscribed depending on the branch it went through — a single output stream shaped differently per item, which Split can’t do since neither of its branches could modify the item without racing the other.

Common Use Cases

  • Conditional transformation: Apply different transformation rules depending on the item’s data
  • Conditional side effects: Only call an API, log, or write to a file when a condition is met
  • Data normalization: Fill in defaults or fix up data only for the records that need it