How to use Laravel Scout in Global Search?

https://filamentphp.com/docs/3.x/tables/advanced#searching-records-with-laravel-scout https://filamentphp.com/docs/4.x/tables/overview#searching-records-with-laravel-scout So lets say i have a songs resource. in the list songs i have:
protected function applySearchToTableQuery(Builder $query): Builder
{
$this->applyColumnSearchesToTableQuery($query);

if (filled($search = $this->getTableSearch())) {
$query->whereIn('songs.id', Song::search($search)->keys());
}

return $query;
}
protected function applySearchToTableQuery(Builder $query): Builder
{
$this->applyColumnSearchesToTableQuery($query);

if (filled($search = $this->getTableSearch())) {
$query->whereIn('songs.id', Song::search($search)->keys());
}

return $query;
}
then, in the table search input, i make a search with a typo. it works. but then, in the global search, it just doesnt work. yeah, in the song resource i added ->searchable and also in the model i defined the toSearchableArray properly is possible to integrate laravel scout in global search without plugins?
4 Replies
ericmp
ericmpOP3d ago
i say without plugins cuz im trying to update from v3 to v4 but i cant because of this. because of this, i mean, because i was using a plugin to be able to search in globally using laravel scout but this plugin isnt available for v4 that is why im trying to find a solution without any plugins and then, i will be able to update i would guess possible solution for v4, if someone thinks this can/should be improved, please let me know how: inside app/Filament/Resources/Songs/SongResource.php
public static function getGlobalSearchResults(string $search): Collection
{
$ids = Song::search($search)->keys()->collect();

if ($ids->isEmpty()) {
return collect();
}

$order = $ids->mapWithKeys(fn (int $id, int $index): array => [(string) $id => $index])->all();

$records = static::getModel()::query()
->whereIn('songs.id', $ids)
->get()
->sortBy(fn (Model $r): int => $order[(string) $r->getKey()] ?? PHP_INT_MAX)
->values();

return $records->map(function (Model $record): ?GlobalSearchResult {
$url = static::getGlobalSearchResultUrl($record);

if (blank($url)) {
return null;
}

return new GlobalSearchResult(
title: static::getGlobalSearchResultTitle($record),
url: $url,
details: static::getGlobalSearchResultDetails($record),
actions: static::getGlobalSearchResultActions($record),
);
})->filter();
}
public static function getGlobalSearchResults(string $search): Collection
{
$ids = Song::search($search)->keys()->collect();

if ($ids->isEmpty()) {
return collect();
}

$order = $ids->mapWithKeys(fn (int $id, int $index): array => [(string) $id => $index])->all();

$records = static::getModel()::query()
->whereIn('songs.id', $ids)
->get()
->sortBy(fn (Model $r): int => $order[(string) $r->getKey()] ?? PHP_INT_MAX)
->values();

return $records->map(function (Model $record): ?GlobalSearchResult {
$url = static::getGlobalSearchResultUrl($record);

if (blank($url)) {
return null;
}

return new GlobalSearchResult(
title: static::getGlobalSearchResultTitle($record),
url: $url,
details: static::getGlobalSearchResultDetails($record),
actions: static::getGlobalSearchResultActions($record),
);
})->filter();
}
Dennis Koch
Dennis Koch3d ago
Looks good. I think another option would be to register a custom GlobalSearchProvider.
ericmp
ericmpOP3d ago
how would u do that?
Dennis Koch
Dennis Koch3d ago
You can bind a custom provider via app->bind(GlobalSearchProvider::class, YourProvider::class). Search for the DefaultGlobalSearchProvider as an example. You could check whether that model is using Scout and apply your logic. Just a thought. I haven't done that before, but might be cleaner than adding it to every resource

Did you find this page helpful?