$this->app->make('content_types')->register('example', [
'label' => 'Examples',
'find' => function (string $q, int $limit, ?array $viewer = null, array $groupIds = []): array {
$rows = $this->app->make('examples')->search($q, $limit, $groupIds);
return array_map(static fn (array $r): array => [
'title' => $r['title'],
'url' => $router->url('example.show', ['slug' => $r['slug']]),
'meta' => 'Example',
'excerpt' => mb_substr($r['summary'], 0, 110),
], $rows);
},
]);🚨 The group ids must reach the query. Filter restricted content out before the LIKE, not after — and never after the LIMIT, or results silently shrink.
🚨 A search result is a disclosure. A title is very often the whole of the secret: "Secret Acquisition Plans" tells you what you needed without opening anything. This has already gone wrong here once, with a restricted page returning 404 when opened and handing a signed-out visitor its title through the search box.
Build the URL from the route rather than writing it out, or it drifts until every result is a 404.