Multi-column search on Laravel Twill model index pages.
I recently had to enable searching via multiple columns on a Laravel Twill 2.0 model index page. As how to do this seems far from obvious, I thought I'd write up a quick how-to guide for anyone else trying to implement it.
Rationale
By default, the index page for a Twill CRUD model has a search bar, which searches for model instances based upon their title
attribute.
I had recently built a site, however, that creates biological records based upon user input. These consist of a species name, alongside a date and location etc; and, therefore, have no logical title. The users of the site wanted to be able to refine the list of records by more than one column (sometimes seeing all the records for a particular location, for example, or of a certain species).
The laravel twill documentation mentions that it is possible to define custom filters on the controller, but doesn't explicitly explain how to do so. Eventually, I discovered several github tickets asking how to enable searching on multiple columns, but none had a complete example, and some resulted in searches which only return results with exact matches.
The code
Eventually, I pieced together a working solution from the various tickets. It just requires adding a method to your Model Repository, and setting a property on the Model Controller.
In app/Repositories/ModelRepository.php
define a custom filter()
method on your Model Repository. Inside this method, call the searchIn()
function and pass it the property names you wish to search in as arguments:
...
/**
* @param \Illuminate\Database\Query\Builder $query
* @param array $scopes
* @return \Illuminate\Database\Query\Builder
*/
public function filter($query, array $scopes = [])
{
$this->searchIn($query, $scopes, 'search', [ // 'search' = search id.
'database_column_1',
'database_column_2',
'database_column_3'
...etc...
]);
return parent::filter($query, $scopes);
}
...
Then, in app/Http/Controllers/Admin/ModelController.php
set the $defaultFilters
property of your Model Controller to the new custom search function:
...
protected $defaultFilters = ['search' => 'search'];
...
In both of these examples ModelController
and ModelRepository
should, of course, be renamed to reflect the name of the model you are enalbing the search on. E.g. UserRepository
.
Making these changes will update the search logic to perform a LIKE
search on all of the columns passed as arguments to searchIn
.