atoolo/graphql-search-bundle
Installation:
composer require sitepark/atoolo-graphql-search-bundle
Add to config/bundles.php:
return [
// ...
Sitepark\AtooloGraphQLSearchBundle\AtooloGraphQLSearchBundle::class => ['all' => true],
];
First Query: Use the built-in GraphQL schema to query search results. Example:
query Search($query: String!) {
search(query: $query) {
results {
id
title
teaser {
headline
content
}
}
facets {
key
count
}
}
}
Key Documentation:
SearchInput to define queries, filters, and sorting.
query Search($input: SearchInput!) {
search(input: $input) {
# Results and metadata
}
}
{
"input": {
"query": "laravel",
"filters": [
{ "field": "contentType", "value": "article" }
],
"sort": { "field": "relevance" },
"page": { "size": 10, "number": 1 }
}
}
facet fields to dynamically filter results:
query Search($query: String!) {
search(query: $query) {
facets {
key
count
values {
value
count
}
}
}
}
MediaTeaser, NewsTeaser) via dependency injection:
# config/services.yaml
Sitepark\AtooloGraphQLSearchBundle\Resolver\Teaser\MediaTeaserResolver:
arguments:
$customFieldResolver: '@app.service.custom_teaser_resolver'
# config/packages/atoolo_graphql_search.yaml
server_side_execution: true
query Search($geoFilter: GeoLocatedFilter!) {
search(filters: [$geoFilter]) {
results {
id
geoLocation {
lat
lng
}
}
}
}
page and sort inputs for pagination/sorting:
query Search($input: SearchInput!) {
search(input: $input) {
results {
edges {
node {
id
title
}
}
pageInfo {
hasNextPage
endCursor
}
}
}
}
Service Integration:
$this->app->bind(
Sitepark\AtooloGraphQLSearchBundle\Resolver\Teaser\CustomTeaserResolver::class,
App\Resolver\CustomTeaserResolver::class
);
Event Listeners:
SearchQueryBuiltEvent):
use Sitepark\AtooloGraphQLSearchBundle\Event\SearchQueryBuiltEvent;
public function onSearchQueryBuilt(SearchQueryBuiltEvent $event) {
$event->getQuery()->addFilter('custom_field', 'value');
}
Configuration:
config/packages/atoolo_graphql_search.yaml:
default_sort: 'relevance'
min_hit_count: 3 # Added in v1.10.0
Testing:
AtooloGraphQLSearchTestCase base class for tests:
use Sitepark\AtooloGraphQLSearchBundle\Test\AtooloGraphQLSearchTestCase;
class MySearchTest extends AtooloGraphQLSearchTestCase {
public function testSearchQuery() {
$this->query('
query { search(query: "test") { results { id } } }
');
}
}
Deprecation Warnings:
symbolicImage was renamed to symbolicAsset in v1.2.0. Update queries/resolvers if using the old field.headline sort criteria was removed in v1.2.0.PHP Version Compatibility:
GeoJSON Edge Cases:
input GeoLocatedFilter {
geometry: String!
# Ensure geometry is valid GeoJSON
}
Caching:
AtooloGraphQLSearchBundle\Event\SearchResultsEvent listeners for caching:
public function onSearchResults(SearchResultsEvent $event) {
Cache::put('search_' . md5($event->getQuery()), $event->getResults());
}
Teaser Resolvers:
Sitepark\AtooloGraphQLSearchBundle\Resolver\Teaser\TeaserResolverInterface. Forgetting to register them will result in missing fields.Relative Date Ranges:
from/to fields for relative date ranges (added in v1.9.0) require a baseOffset for accurate filtering:
input RelativeDateRangeFilter {
from: Int! # Days from baseOffset
to: Int! # Days from baseOffset
baseOffset: Int # Optional (e.g., -7 for "last week")
}
Query Analysis:
explain field to debug search logic:
query Search($query: String!) {
search(query: $query) {
explain
}
}
Logging:
config/packages/atoolo_graphql_search.yaml:
debug: true
Schema Validation:
php bin/console debug:graphql
Performance:
minHitCount).Custom Resolvers:
AssetResolver) or create new ones:
namespace App\Resolver;
use Sitepark\AtooloGraphQLSearchBundle\Resolver\Asset\AssetResolverInterface;
class CustomAssetResolver implements AssetResolverInterface {
public function resolve($asset, array $context) {
// Custom logic
return [
'url' => $asset->getCustomUrl(),
'alt' => $asset->getCustomAlt(),
];
}
}
Query Modifiers:
SearchQueryBuiltEvent to modify queries dynamically:
$event->getQuery()->addSort('custom_field', 'asc');
Teaser Factories:
MediaTeaserFactory) to customize teaser generation:
namespace App\Factory;
use Sitepark\AtooloGraphQLSearchBundle\Factory\Teaser\MediaTeaserFactory as BaseFactory;
class CustomMediaTeaserFactory extends BaseFactory {
protected function createTeaser(): array {
$teaser = parent::createTeaser();
$teaser['customField'] = 'value';
return $teaser;
}
}
Context Dispatchers:
ContextDispatcher to add custom context data:
namespace App\Dispatcher;
use Sitepark\AtooloGraphQLSearchBundle\Dispatcher\ContextDispatcherInterface;
class CustomContextDispatcher implements ContextDispatcherInterface {
How can I help you explore Laravel packages today?