To ensure security and stability, the coding environment has specific constraints.
$a - $z)You may use internal variables for calculations, but you are strictly limited to single-letter variable names ranging from $a to $z.
✅ Allowed: $x = 10;
❌ Error: $total_price = 10;
return statement. Modify the $output array directly. You can change existing values or add new keys.The PHP environment is restricted to "safe expressions." Complex functions or external calls may result in errors.
Lowercase: All column headers are converted to lowercase.
Underscores: Spaces and special characters are replaced with _.
You can use the global variable $output to skip rows or trigger warnings and errors based on your logic.
| Action | Code Implementation | Result |
| Skip Row | $output['success'] = 'Success message'; | The row is ignored. Processing continues to the next row without error. |
| Trigger Error | $output['error'] = 'Invalid SKU'; | The import stops immediately with an error. |
| Trigger Warning | $output['error'] = 'Warning: Stock low'; | The import logs a warning and stops processing (if prefix is 'Warning: '). |
$output VariableThe core of this feature is the global $output variable. This variable acts as both your input (reading the spreadsheet) and your output (sending data to SmartIMPORT). When your code runs, $output is already populated with the data from the current spreadsheet row.
return statement. Modify the $output array directly. You can change existing values or add new keys.Scenario: Your spreadsheet has "First Name" and "Last Name", but the system needs a "Full Name" field.
// Define a temporary variable for spacing $s = ' '; // Combine the normalized keys into a new key $output['full_name'] = $output['first_name'] . $s . $output['last_name'];
Scenario: You want to add a 20% tax to the price, but only if the "Taxable" column is marked "Yes".
// Check if item is taxable if ($output['taxable'] == 'Yes') { // Use $p as a temporary variable for the calculation $p = $output['price']; $output['price_inc_tax'] = $p * 1.20; } else { $output['price_inc_tax'] = $output['price']; }
Scenario: Skip the row entirely if the "Status" column is set to "Inactive".
if ($output['status'] == 'Inactive') { // Set output to null to stop processing this specific row $output = null; }
In this stage, you have access to the $input array, which contains two crucial sets of data:
$input['event'])This contains the raw data from your spreadsheet row (normalised with lowercase keys), precisely as it appeared in the initial processing step.
$input['search'])This object contains the results of the system's attempt to match the row to an existing constituent. It tells you whether a match was found and provides details about that record.
To write effective logic, you need to understand the structure of $input['search']. Below is a reference schema showing the most common fields.
cons object contains the existing database record. If no match was found, some of these fields may be null or empty. The below is a JSON equivalent of the array based $input['search'] value. As an example $input['search']['cons'] will access the constituent data and $input['search']['cons']['gender'] will return 'Male'.{ "id": "185", // The System ID of the found record "lookup_id": "1001", // The user-facing ID "record_already_exists": true, // Boolean: true if a match was found "cons": { // The "Constituent" details object "id": "185", "first": "John", "last": "Doe", "title": "Mr.", "type": "Individual", "gender": "Male", "birthdate": { "d": 14, "m": 3, "y": 1980 }, "address": { "address_lines": "123 Main St", "city": "Denver", "state": "CO", "postal_code": "80202", "country": "United States", "type": "Home", "do_not_mail": false }, "email": { "address": "john.doe@example.com", "type": "Email", "do_not_email": false }, "phone": { "number": "(555) 123-4567", "type": "Home", "do_not_call": false }, "spouse": { "first": "Jane", "last": "Doe" } } }
You can use this data to perform complex logic. As with the pre-processing step, you modify the global $output variable to control the flow.
Scenario: If the record already exists and is marked as "Deceased" in the database, do not process this row.
// Check if match exists if (array_key_exists('record_already_exists',$input['search']) && $input['search']['record_already_exists']) {// Check the 'deceased' flag in the 'cons' object if ($input['search']['cons']['deceased'] == true) { // Set output to null to stop processing this row entirely $output = null; } }
Scenario: You want to log a warning if the spreadsheet address is different from the database address.
if (array_key_exists('record_already_exists',$input['search']) && $input['search']['record_already_exists']) {// Get the database zip code (from search/cons) $z = $input['search']['cons']['address']['postal_code']; // Get the spreadsheet zip code (from event) $y = $input['event']['zip_code']; // Assuming column header is 'Zip Code' // Compare first 5 digits if (substr($z, 0, 5) != substr($y, 0, 5)) { // Stop the flow with a warning$output['error'] = 'Warning: Address mismatch detected.'; } }
This process works in a two-step cycle:
Request Phase: Your code checks if data is missing. If so, it assigns a command array to $output. The system detects this, pauses your code, and fetches the data.
Processing Phase: The system re-runs your code, this time populating $output with the requested data and a completion flag.
To trigger a function, you must structure the $output['command'] array as follows:
$output['command'] = [ 'function' => 'lookup', 'arguments' => [ 'use_default' => 'true', 'return_rows' => false, // Set to true if you need the full row data 'mode' => 'normal', 'searches' => [ [ 'spreadsheet' => '123456789', // The ID of the external sheet 'search' => 'value_to_find', // The value to search for 'matching' => 'exact' // 'exact' or 'contains' ] ] ] ];
When the system returns the data, two new keys are available in the global variable:
$output['lookups_done']: (Boolean) Returns true indicates the lookup has finished.
$output['lookups_data']: (Array) Contains the results of the search.
Scenario: You are importing orders. You have a product_id but need the product_name one that lives in a different spreadsheet (ID 987654321).
// Step 1: Check if the lookup has been performed yet if (empty($output['lookups_done'])) { // PREPARE THE LOOKUP // We want to search the external sheet for the product_id from the current row $output['command'] = [ 'function' => 'lookup', 'arguments' => [ 'use_default' => 'true', 'return_rows' => false, 'mode' => 'normal', 'searches' => [ [ 'spreadsheet' => '987654321', // The external Product Database ID 'search' => $output['product_id'], 'matching' => 'exact' ] ] ] ]; } else { // Step 2: Process the results // The system has returned with the data. // Remember to use single-letter variables ($a-$z). $d = $output['lookups_data']; // Assuming the lookup returns an array where the first item is the result if (!empty($d)) { $output['product_name'] = $d[0]; } else { $output['product_name'] = 'Unknown Product'; } }
if/else block checking for lookups_done. Without this check, the code may enter an infinite loop of requesting data.