Skip to content

Drivers And Logging

Search exposes a public frontend route and records first-party search behavior when logging is enabled. The search backend is behind Capell\Search\Contracts\Search.

KeyUse
capell-search.enabledEnables frontend search.
capell-search.show_header_searchRegisters the header search render hook.
capell-search.driverdatabase or scout; defaults from CAPELL_SITE_SEARCH_DRIVER.
capell-search.route_pathPublic route path, default search.
capell-search.results_per_pageDefault pagination size.
capell-search.excerpt_lengthGenerated excerpt length.
capell-search.minimum_query_lengthRejects short queries.
capell-search.record_search_logsWrites query and click logs.
capell-search.hash_visitor_dataHashes visitor identifiers in logs.
capell-search.database.*Database driver table and column mapping.
capell-search.scout.*Scout model and column mapping.
capell-search.logs.retention_daysRetention window for purge behavior.

The database driver expects a flat searchable source. Do not point it at a table whose title, body, URL, or type values live only in nested JSON unless the configured columns can be queried directly. For standard Capell pages, use a flattened index table/view, bind a custom Search implementation, or switch to Scout.

Bind the contract when a package needs a custom backend.

use Capell\Search\Contracts\Search;
use Capell\Search\Data\SearchResultData;
use Illuminate\Contracts\Pagination\LengthAwarePaginator;
use Illuminate\Pagination\LengthAwarePaginator as Paginator;
final class DemoSearchDriver implements Search
{
public function search(string $query, int $perPage = 10, int $page = 1): LengthAwarePaginator
{
$results = collect([
new SearchResultData(
title: 'About Capell',
url: '/about',
excerpt: $this->highlight('About Capell CMS', $query),
type: 'page',
score: 1.0,
),
]);
return new Paginator($results, $results->count(), $perPage, $page);
}
public function highlight(string $text, string $query): string
{
return str_ireplace($query, '<mark>' . e($query) . '</mark>', e($text));
}
}
$this->app->singleton(Search::class, DemoSearchDriver::class);

Escape text before adding markup. Search results are rendered on public pages.

Use package actions instead of writing SearchLog rows directly:

  • RecordSearchAction
  • RecordSearchResultClickAction
  • PurgeSearchLogsAction

Hash visitor data unless a product requirement says otherwise.

Terminal window
vendor/bin/pest packages/search/tests --configuration=phpunit.xml