Search
In Forest Admin, pages which show lists of records have a free-text search widget on top of them.

A search bar on the main list-view
Two search modes are supported: normal and extended.
- All searches start by being a "normal search".
- If the result the user is looking for is not found, it is possible to trigger an extended search from the user interface.

Extended search call to action
When not defined otherwise by the data source, the search behavior is to attempt to search within columns of the collection (in normal mode), or columns of the collection of direct relations (in extended mode).
By default, Forest Admin will search only on some columns, depending on their respective types.
Column Type | Default search behavior |
---|---|
Enum | Column is equal to the search string (case-insensitive) |
Number | Column is equal to the search string (if the search string is numeric) |
String | Column contains the search string (case-insensitive) |
Uuid | Column is equal to the search string |
Other types | Column is ignored by the default search handler |
You may want to change how the search bar behaves in your admin panel.
For instance:
- Search only on the columns which are relevant to your use case.
- Use full-text indexes of your data (i.e Postgres
tsquery
andtsvector
, Algolia, Elastic search, ...)
In this example, we use the
searchExtended
condition to toggle between case-sensitive and insensitive searches.use ForestAdmin\AgentPHP\DatasourceCustomizer\CollectionCustomizer;
use ForestAdmin\AgentPHP\DatasourceToolkit\Components\Query\ConditionTree\Operators;
$forestAgent->customizeCollection(
'People',
function (CollectionCustomizer $builder) {
$builder->replaceSearch(
function ($searchString, $extendedMode) {
$operator = $extendedMode ? Operators::CONTAINS : Operators::ICONTAINS;
return [
'aggregator' => 'Or',
'conditions' => [
['field' => 'firstName', 'operator' => $operator, 'value' => $searchString],
['field' => 'lastName', 'operator' => $operator, 'value' => $searchString],
]
];
}
);
}
);
use ForestAdmin\AgentPHP\DatasourceCustomizer\CollectionCustomizer;
use ForestAdmin\AgentPHP\DatasourceToolkit\Components\Query\ConditionTree\Operators;
$forestAgent->customizeCollection(
'Product',
function (CollectionCustomizer $builder) {
$builder->replaceSearch(
function ($searchString, $extendedMode) {
$productReferenceRegexp = '/^[a-f]{16}$/i';
$barCodeRegexp = '/^[0-9]{10}$/i';
// User is searching using a product reference.
if (preg_match($productReferenceRegexp, $str)) {
return ['field' => 'reference', 'operator' => Operators::EQUAL, 'value' => $searchString];
}
// User is search a bar-code
if (preg_match($barCodeRegexp, $str)) {
return ['field' => 'barCode', 'operator' => Operators::EQUAL, 'value' => $searchString];
}
// User is searching something else, in "normal mode", let's only search in the product name
if (! $extendedMode) {
return ['field' => 'name', 'operator' => Operators::CONTAINS, 'value' => $searchString];
}
// In extended mode, we search on name, description and brand name
return [
'aggregator' => 'Or',
'conditions' => [
['field' => 'name', 'operator' => Operators::CONTAINS, 'value' => $searchString],
['field' => 'description', 'operator' => Operators::CONTAINS, 'value' => $searchString],
['field' => 'brand:name', 'operator' => Operators::EQUAL, 'value' => $searchString],
]
];
}
);
}
);
If your data is indexed using a SaaS, external store, or full-text index, you can call it in the search handler.
use ForestAdmin\AgentPHP\DatasourceCustomizer\CollectionCustomizer;
use ForestAdmin\AgentPHP\DatasourceToolkit\Components\Query\ConditionTree\Operators;
use Algolia\AlgoliaSearch\SearchClient;
$forestAgent->customizeCollection(
'Product',
function (CollectionCustomizer $builder) {
$builder->replaceSearch(
function ($searchString, $extendedMode) {
$client = SearchClient::create("YourApplicationID", "YourWriteAPIKey");
$index = $client->initIndex("test_index");
$results = $index->search(
$searchString,
[
'attributesToRetrieve' => ['id'],
'hitsPerPage' => 50,
]
);
return ['field' => 'id', 'operator' => Operators::IN, 'value' => array_map(fn ($hit) => $hit['id'], $results)];
}
);
}
);
Last modified 1mo ago