A job is a trigger, conditions and an ordered list of actions, set up under Customization › Orchestration in the admin; jobs were called hooks before the module was renamed, and the API's routes keep that name. What starts a job, what it can do, branches and loops, email, scheduled work, integrations with other systems, and every event and action.
L2–L3
Unit 04 · Branches, loops and re-runs
Conditions: if, else if and else
Branches, loops and re-runsPage 16 of 31Updated
A condition runs the first of its branches that matches, or its else. The two branch types, the two ways a branch matches without checking anything, branching on a value, a comparison and the presence of a record, and how to keep a branching job readable.
Who this is for. Anyone whose job must decide something. Afterwards you can write a branch that matches when you mean it to, and only then.
How a condition runs
A Condition action holds branches: an IF, any number of ELSEIF, and at most one ELSE. Each branch holds its own actions. The branches are tried in order and the first that matches runs; the rest are ignored. If none matches and there is no else, the condition is skipped and the job carries on after it. The run log records the outcome as Matched condition: followed by the branch's description, No condition matched; running ELSE, or No condition matched and no ELSE provided, so give every branch a description that says what it means.
Each branch has a Condition type:
Type
Matches when
Entity event
The record the run's entity event is about fits the Criteria you give for the chosen Entity
Template
Its template code calls result.setMatching(true)
Two branches that match without checking
A template branch matches only when it calls setMatching(true). Printing a value, or a template that evaluates to true, does nothing: the branch is false unless the call is made.
An entity event branch matches without any check when its criteria are empty, or when the run's record belongs to another entity than the one the branch names. A job with triggers on two entities therefore runs the branch for both. In a run not started by an entity event, the branch never matches. When a job's triggers cover several entities, test the entity in a template branch instead.
Branching on a value, a comparison and a record
Template code
{* on a value: a form answer *}
{if $event->getRecord()->getData()['topic'] == 'sales'}{$result->setMatching(true)}{/if}
{* on a comparison: at least five orders found *}
{if $runData->get('find-orders')->records|count >= 5}{$result->setMatching(true)}{/if}
{* on the presence of a record: exactly one contact found *}
{if $runData->get('find-contact')->record}{$result->setMatching(true)}{/if}
{# on a value: a form answer #}
{% if event.getRecord().getData().topic == 'sales' %}{% do result.setMatching(true) %}{% endif %}
{# on a comparison: at least five orders found #}
{% if runData.get('find-orders').records|length >= 5 %}{% do result.setMatching(true) %}{% endif %}
{# on the presence of a record: exactly one contact found #}
{% if runData.get('find-contact').record %}{% do result.setMatching(true) %}{% endif %}
A Retrieve Records leaves record only when exactly one record matched. To branch on "at least one", test the count of records instead.
Keeping a branching job readable
Branches nest: a branch can hold another condition. Two habits keep a job readable:
Test the reason to stop first. A top-level condition whose only branch is "not for us" and holds a Stop leaves everything after it as the main path, with no nesting (Stopping a job early).
Two levels of nesting is the limit. Past that, split the job: the deeper branch becomes its own job, started with Trigger job (Chaining one job to another).
Name each condition and branch for what it decides (is-sales, contact-exists), and the job's action list reads as its logic.