/

Relation Dropdowns

Turn a raw foreign-key column into a dropdown, searchable combobox, or multi-select resolved against another table with relation().

What relation() does

relation() binds a real, editable column on the current table (e.g. payments.customerNumber) to a lookup against another table. The create/edit form shows a dropdown of that table's rows instead of a bare numeric id input, and the list shows the resolved name in place of the raw id.

$xcrud->relation(
    'customerNumber', 'customers', 'customerNumber', 'customerName',
    "country = 'USA'", null, false, ' ', null, null, null, true
);

The target table must itself be reachable the same way any other table on the site is - a real table, not blacklisted, with a single-column primary key. It doesn't need its own CRUD page; relation() can read a table nothing else on the site ever browses directly.

Parameters

ParameterTypeDefaultDescription
$fieldstring-The real, editable column on this table to bind (e.g. customerNumber).
$targetTablestring-The table to look values up in.
$targetIdstring-Column on $targetTable whose value is stored back into $field.
$targetNamestring|array-Column(s) shown as the option label. An array (e.g. ['contactFirstName', 'contactLastName']) is joined with $concatSeparator to show something like "First Last".
$wherearray|string|nullnullNarrows which target rows are offered. An array is safe column=>value equality, ANDed together and bound as parameters. A string is trusted, developer-authored raw SQL (same trust level as where_raw()), optionally with {field} placeholders substituted with the current row's own value.
$orderBystring|nullnullSort order for the option list.
$multiboolfalseRenders a multi-select instead of a single dropdown; the stored value becomes a comma-joined list of ids.
$concatSeparatorstring' 'Separator used when $targetName is an array of columns.
$treemixednullReserved for a future hierarchical/indented-tree dropdown - not implemented yet; passing a non-default value throws.
$dependFieldstring|nullnullColumn on $targetTable to filter by, compared against $dependOn's current value. See Cascading / Dependent Dropdowns.
$dependOnstring|nullnullName of another relation()-configured field on this table whose current selection drives the filter above.
$searchboolfalseRenders a searchable combobox (a text input that filters the fetched option list as you type) instead of a plain <select> - useful once there are dozens of options. Combines with $multi for removable chips.

Filtering the option list

The array form of $where is the safe default - simple equality, parameterized:

$xcrud->relation('catid', 'categories', 'cid', 'name', ['published' => 1]);

The string form is a raw SQL fragment for anything an equality array can't express - it's trusted, developer-authored SQL, never built from user input:

$xcrud->relation('customerNumber', 'customers', 'customerNumber', 'customerName', "country = 'USA'");

Whichever form is used, the whole relation configuration - table, id column, name column(s), where, order, multi - is HMAC-signed with XcrudConfig::$appSecret the same way a base where() filter is, so it can't be retargeted or widened by editing anything client-side.

subselect(): a read-only computed column

Where relation() resolves an editable foreign key, subselect() adds a display-only column computed from an arbitrary correlated SQL expression - nothing is stored back into it, and it's never editable, sortable, or searchable.

$xcrud->subselect(
    'orderCount',
    'SELECT COUNT(*) FROM orders o WHERE o.customerNumber = payments.customerNumber'
);

$field becomes a new column alongside the table's real ones and must be a valid identifier that isn't already a real column name. $sql is trusted, developer-authored SQL - like relation()'s raw $where string, it is HMAC-signed with XcrudConfig::$appSecret when the page renders and re-verified on every request, so a visitor can't tamper with it, but it is never validated or sandboxed against what you write - keep it server-authored, never assembled from request input.

Cascading dropdowns

$dependField/$dependOn make one relation dropdown's options filter based on another field's currently selected value on the same form - e.g. a City dropdown that only offers cities in the currently-selected Country. See Cascading / Dependent Dropdowns for the full walkthrough, including multi-level chains.