Filter Tabs
Turn where()/or_where()'s optional trailing $tab argument into a visitor-switchable tab strip above the grid.
Base filters vs. tabs
where()/or_where() without a trailing $tab argument add a permanent, always-applied, server-enforced base filter - HMAC-signed with XcrudConfig::$appSecret so a visitor can't widen or remove it by editing the URL. Add a $tab argument and the same condition instead becomes one option in a named, visitor-switchable tab strip rendered above the grid - click a tab to swap which condition is active.
public function where(string $field, ?string $operator = null, ?string $value = null, ?string $tab = null): self
public function or_where(string $field, ?string $operator = null, ?string $value = null, ?string $tab = null): self
Both accept either the 3-argument symbol/named-operator style (=, !=, >, >=, <, <=, or codes like eq/neq/gt/contains/starts/ends) or a single combined-string shorthand for symbol operators only (->where('amount > 500')). With the shorthand, $tab lands in the otherwise-unused 2nd argument slot.
A 3-tab example
Every where() call sharing the same tab label belongs to that tab and combines with the others exactly like untabbed calls do - AND, in call order:
$xcrud->where('status', '=', 'active', 'Active');
$xcrud->where('status', '=', 'archived', 'Archived');
$xcrud->where('amount', '>', '0', 'All');
Clicking "Archived" applies only status = 'archived'; it does not also apply "Active"'s condition. Each tab is independently signed and tamper-proof, the same as an ordinary where() call - a visitor can only ever pick between exactly the page-author-approved tabs, never forge a different filter by editing the URL.
A tab can combine more than one condition - two where() calls sharing a label produce a genuine AND between them, not two unrelated conditions that happen to share a name:
$xcrud->where('amount', '>=', '1000', 'Medium');
$xcrud->where('amount', '<=', '50000', 'Medium');
Parameters
| Parameter | Type | Default | Description |
|---|---|---|---|
$field | string | - | Column name, or the whole combined condition when using the single-string shorthand. |
$operator | string|null | null | Symbol (=, !=, >, >=, <, <=) or named code (eq, neq, gt, gte, lt, lte, contains, starts, ends). Omit when using the single-string shorthand. |
$value | string|null | null | Value to compare against. Omit when using the single-string shorthand. |
$tab | string|null | null | Tab label. Leaving it out keeps the call a permanent base filter; setting it groups the condition under a visitor-switchable tab. |
where_raw() / or_where_raw(): the raw-SQL tab
Some conditions have no "field OP value" shape - an IN (subquery), for instance. where_raw($condition, $tab = null) and or_where_raw($condition, $tab = null) insert $condition verbatim (parenthesized) into the WHERE clause, with no parsing, whitelisting, or parameter binding at all - the same trust level as subselect()'s raw SQL. Never build $condition from request input; it must be a literal string you wrote, exactly like any other SQL in your codebase.
public function where_raw(string $condition, ?string $tab = null): self
public function or_where_raw(string $condition, ?string $tab = null): self
$xcrud->where_raw(
'customerNumber IN (SELECT customerNumber FROM payments GROUP BY customerNumber HAVING COUNT(*) > 5)',
'Repeat Customers'
);
It travels to the API the same way an ordinary where() condition does - part of the same base-where payload, covered by the same one HMAC signature - so it's just as tamper-proof, with no separate signing of its own. It accepts the same optional trailing $tab argument to make it switchable as part of a filter tab, and composes with tabs built from where() the normal way.
Date-range tabs
where_raw() is also what powers cumulative date-range filter tabs (This Week / This Month / This Year) - see Date Range Filters for that walkthrough specifically.