DAO Search Filter Syntax

DataAccessObject::select(), update(), and delete() accept a $search array where each entry is column => value. By default the operator is =, but the column key can carry an &OPERATOR suffix to choose a different one. This page is the canonical reference for the supported suffixes.

Convention: Always assign the condition array to a local $search variable before passing it to the DAO. This makes call sites consistent and easier to read.

Default — Equality

$search = [
    'status' => 'active',          // status = 'active'
    'id'     => 42,                // id     = 42
];
$rows = $this->select('users', $search);

null becomes IS NULL:

$search = [
    'parent_id' => null,           // parent_id IS NULL
];

Negation And NULL Checks

$search = [
    'status&!='        => 'deleted',  // status <> 'deleted'
    'parent_id&IS'     => null,       // parent_id IS NULL
    'parent_id&IS NOT' => null,       // parent_id IS NOT NULL
];

Comparison

Suffix SQL
&> >
&>= >=
&< <
&<= <=
$search = [
    'price&>='      => 100,
    'created_at&<'  => '2026-01-01',
];

Set Membership

$search = [
    'status&IN'     => ['active', 'draft'],   // status IN (...)
    'status&NOT IN' => ['deleted'],           // status NOT IN (...)
];

Always check that the array is non-empty before passing it to the DAO — passing an empty array currently raises an error.

Pattern Matching

$search = [
    'caption&LIKE'   => '%Festi%',
    'caption&ILIKE'  => '%festi%',     // PostgreSQL only
];

The wildcard characters (%, _) are not escaped — supply them yourself and quote any user input separately if needed.

Subqueries

Raw SQL strings are not allowed in plugin or business code. Build subqueries with the Query builder or wrap a fragment in Expression, then pass the resulting object as the search value.

use core\dao\Query;

$query = new Query($this->db);
$query->column('1')
    ->from('orders')
    ->where(['orders.user_id' => new Expression('users.id')]);

$search = [
    '&EXISTS' => $query,
];

For multiple EXISTS clauses on the same query, prefix the key with any unique label so the array keys remain distinct (e.g. 'one&EXISTS', 'two&EXISTS'). See the README section on EXISTS and NOT EXISTS conditions for more variants, including Query and Expression usage.

Arithmetic Updates

The + and - suffixes (no &) are used in the values array of update() to apply an incremental change instead of a literal assignment:

$search = ['id' => $userID];
$values = [
    'login_count+' => 1,
    'balance-'     => 100,
];
$this->update('users', $values, $search);

OR Conditions

Wrap an array of sub-searches under the sql_or key:

$search = [
    'status' => 'active',
    'sql_or' => [
        ['type' => 'admin'],
        ['type' => 'editor', 'verified' => true],
    ],
];

This produces status = 'active' AND ((type = 'admin') OR (type = 'editor' AND verified = TRUE)).

Order, Limit, Offset

These are separate arguments — they are not keys in the $search array.

$rows = $this->select(
    'contents',
    $search,
    ['cdate DESC'],   // order by
    20,                // limit
    40                 // offset
);