More adapters soon...
Jon Watts
Johannes Roberts
Lana Wachowski
Byron Howard
Andy Serkis
Rawson Marshall Thurber
Destin Daniel Cretton
James Cullen Bressack
Adam McKay
Garth Jennings
Walt Becker
ChloΓ© Zhao
Install and configure the bundle in minutes. Nice and easy
Enhance your search results with advanced filtering and sorting options
Real-time search results ensuring a smooth and dynamic experience
Designed to deliver fast and accurate search results, even with large datasets
Works effortlessly with Doctrine and Symfony's ecosystem
Adapt search behavior and result formatting to match your exact needs
Spend less time managing search logic and more time building great features.
Let Ux-Search handle the complexity for you !
Install the bundle via Composer:
composer require mezcalito/ux-search
If you're not using Symfony Flex, you'll need to manually register the bundle in config/bundles.php:
// config/bundles.php
return [
// ...
Mezcalito\UxSearchBundle\MezcalitoUxSearchBundle::class => ['all' => true],
];
Create a configuration file config/packages/mezcalito_ux_search.yaml:
mezcalito_ux_search:
default_adapter: 'default'
adapters:
default: '%env(MEZCALITO_UX_SEARCH_DEFAULT_DSN)%'
Add the DSN to your .env file (choose one):
# For Algolia
MEZCALITO_UX_SEARCH_DEFAULT_DSN=algolia://YOUR_API_KEY@YOUR_APP_ID
# For Meilisearch
MEZCALITO_UX_SEARCH_DEFAULT_DSN=meilisearch://YOUR_MASTER_KEY@localhost:7700
# For Doctrine ORM
MEZCALITO_UX_SEARCH_DEFAULT_DSN=doctrine://default
Use the maker command to generate a search class:
php bin/console make:search
The command will ask you for:
App\Entity\Product)default_adapter)This creates a search class in src/Search/ that you can customize.
In any Twig template:
{# Using Twig component syntax #}
<twig:Mezcalito:UxSearch:Layout name="product"/>
{# Or using component function #}
{{ component('Mezcalito:UxSearch:Layout', { name: 'product' }) }}
That's it! You now have a working search with facets, pagination, and live updates. π
Three adapters are available, each with different strengths:
| Adapter | Best For | Performance | Cost | Setup Complexity |
|---|---|---|---|---|
| Algolia | Production, large datasets | βββ | π° Paid | Easy |
| Meilisearch | Self-hosted production | βββ | π Free | Medium |
| Doctrine | Development, small datasets | ββ | π Free | Very Easy |
| Adapter | DSN Format | Documentation |
|---|---|---|
| Algolia | algolia://apiKey@appId |
View docs |
| Meilisearch | meilisearch://key@host:port |
View docs |
| Doctrine | doctrine://entityManagerName |
View docs |
Need another provider? You can create your own adapter.
Once you've created a search class, customize it by editing the build() method:
use Mezcalito\UxSearchBundle\Search\AbstractSearch;
use Mezcalito\UxSearchBundle\Attribute\AsSearch;
use Mezcalito\UxSearchBundle\Twig\Components\Facet\RangeInput;
#[AsSearch(index: 'products', adapter: 'default')]
class ProductSearch extends AbstractSearch
{
public function build(array $options = []): void
{
// Add facets for filtering
$this->addFacet('brand', 'Brand');
$this->addFacet('category', 'Category');
$this->addFacet('price', 'Price', RangeInput::class);
// Add sorting options
$this->addAvailableSort('name', 'Name');
$this->addAvailableSort('price', 'Price');
$this->addAvailableSort('created_at', 'Newest');
// Configure pagination
$this->setAvailableHitsPerPage([12, 24, 48]);
// Adapter-specific parameters
$this->setAdapterParameters([
// Adapter-specific options here
]);
}
}
The bundle provides a complete set of UI components that you can use individually or override:
| Component | Description | Documentation |
|---|---|---|
| Layout | Root wrapper component containing all search elements | Docs |
| SearchInput | Text search input with live updates | Docs |
| Hits | Display search results with customizable item templates | Docs |
| Pagination | Navigate through search results | Docs |
| Component | Description | Documentation |
|---|---|---|
| RefinementList | Checkbox/radio list for categorical filtering | Docs |
| RangeInput | Min/max input fields for numeric ranges | Docs |
| RangeSlider | Slider for numeric range filtering | Docs |
| Component | Description | Documentation |
|---|---|---|
| CurrentRefinements | Display active filters with remove buttons | Docs |
| ClearRefinements | Button to clear all active filters | Docs |
| SortBy | Dropdown to change sort order | Docs |
| TotalHits | Display total number of results | Docs |
You can override any component template by creating a file in your app's templates/ directory:
templates/
βββ components/
βββ Mezcalito/
βββ UxSearch/
βββ Layout.html.twig # Override the main layout
βββ SearchInput.html.twig # Override search input
βββ Hits.html.twig # Override results display
βββ Facet/
βββ RefinementList.html.twig
The most common customization is the hit (result item) template. Override Hits.html.twig:
{# templates/components/Mezcalito/UxSearch/Hits.html.twig #}
<div {{ attributes }}>
{% for hit in this.resultSet.hits %}
<article class="product-card">
<img src="{{ hit.image }}" alt="{{ hit.name }}">
<h3>{{ hit.name }}</h3>
<p class="price">{{ hit.price|format_currency('EUR') }}</p>
<a href="{{ path('product_show', {id: hit.id}) }}">View details</a>
</article>
{% endfor %}
</div>
Customize search behavior with event subscribers:
use Mezcalito\UxSearchBundle\Event\PreSearchEvent;
use Symfony\Component\EventDispatcher\EventSubscriberInterface;
class SearchSubscriber implements EventSubscriberInterface
{
public static function getSubscribedEvents(): array
{
return [
PreSearchEvent::class => 'onPreSearch',
];
}
public function onPreSearch(PreSearchEvent $event): void
{
$query = $event->getQuery();
// Modify the query before search execution
$query->addFilter('status', 'published');
}
}
π Event system documentation
You can have multiple search configurations in one application:
// Product search with Algolia
#[AsSearch(index: 'products', adapter: 'algolia')]
class ProductSearc