Skip to content

TextFilter

Filters by text in one column, in joined columns or in SQL expressions. The text is found anywhere; * is a wildcard like in the search.

use Anvil\Collection\Filters\TextFilter;
TextFilter::make('city'),
TextFilter::make('number')->exact(),
TextFilter::make('person')->queryColumn('p.last_name', 'p.first_name'),
TextFilter::make('person')->expression("CONCAT(p.first_name, ' ', p.last_name)", "CONCAT(p.last_name, ' ', p.first_name)"),
Option Effect Default
exact() equal instead of contains; * stays a wildcard contains
maxLength(n) longest input, 1 to 255 100
placeholder('…') placeholder of the input “contains…” / “equals…”
queryColumn('p.a', 'p.b') filter these columns (e.g. of a join); a record matches if any matches the filter column
expression('CONCAT(…)', …) filter SQL expressions; a record matches if any matches –

Plus label() and column().

A search input. The list updates 0.4 seconds after typing stops, or on Enter.

Unlike the search, the text is not split into words: Hans Müller is one term.

Text Default (contains) exact()
berlin contains “berlin” is “berlin”
ber* starts with “ber” starts with “ber”
*lin ends with “lin” ends with “lin”
b*n starts with “b”, ends with “n” starts with “b”, ends with “n”

% and _ are matched literally. A text of only * is no filter. Case follows the collation of the column (case-insensitive with the usual utf8mb4_*_ci).

public function scopeQuery(Model $model): void
{
$model->select('contacts.*, p.last_name, p.first_name')
->join('people p', 'p.id = contacts.person_id');
}
// in collection():
TextFilter::make('person')->queryColumn('p.last_name', 'p.first_name'),

Each column is matched on its own: Mül* finds “Müller”, but Hans Müller matches neither column.

A name composed of two columns is filtered as an expression; give both orders so users can type either:

TextFilter::make('person')->label('Person')
->expression("CONCAT(p.first_name, ' ', p.last_name)", "CONCAT(p.last_name, ' ', p.first_name)"),
  • A record matches if any expression matches. Hans Mü* and Mül* find “Hans Müller”.
  • The expressions are inserted into the SQL as they are: static code of the application, never input. ;, --, /* and # are rejected (InvalidArgumentException). The filter text itself is bound as a parameter.
  • Table names in expressions are not prefixed (DBPrefix): use the join aliases (p.) and columns of the main table without the table name.

The text as entered: 'Berlin', 'mei*'. API: filter[city]=Berlin.