Search by

atomicptr / symfony-indexed-search

atomicptr

Indexed Search is a Symfony bundle that provides a straightforward database-powered search functionality for Doctrine entities. It makes implementing search across your application's data simple, flexible and easy to integrate.

Package info

github.com/atomicptr/symfony-indexed-search

Type:symfony-bundle

pkg:composer/atomicptr/symfony-indexed-search

Fund package maintenance!

atomicptr

Buy Me A Coffee

Statistics

Installs: 8

Dependents: 0

Suggesters: 0

Stars: 0

Open Issues: 0

v0.2.0 2026-11-10 18:58 UTC

This package is auto-updated.

Last update: 2026-11-10 19:01:00 UTC


README

Indexed Search is a Symfony bundle that provides a straightforward database-powered search functionality for Doctrine entities. It makes implementing search across your application's data simple, flexible and easy to integrate.

Requirements

  • PHP 8.5+ (ext-intl required) and Symfony 8
  • Doctrine
  • SQLite, MySQL, MariaDB or PostgreSQL

Installation

composer require atomicptr/symfony-indexed-search

Make sure it's installed in your config/bundles.php:

Atomicptr\Symfony\IndexedSearch\IndexedSearchBundle::class => ['all' => true],

You might also need to create migrations for our index tables:

bin/console doctrine:migrations:diff
bin/console doctrine:migrations:migrate

Usage

Mark what you want to search and what you want to filter by:

#[ORM\Entity]
#[Searchable(filters: ['type' => 'product'])] // fixed filters for every product
class Product
{
    #[ORM\Column]
    #[SearchableText(weight: Weight::Highest)] // Highest, High, Normal (default) or Low
    private string $name;

    #[ORM\Column(type: 'text')]
    #[SearchableText(format: TextFormat::Html)] // optional, strips the HTML
    private string $description;

    #[ORM\Column]
    #[SearchableFilter('tenant')]
    private int $tenantId;

    #[ORM\Column]
    #[SearchableDate] // optional, for sorting by date
    private DateTimeImmutable $createdAt;

    #[ORM\Column]
    #[SearchableWhen] // optional, only indexed while true
    private bool $published;
}

Build the index:

bin/console indexed-search:index

And search:

$result = $searchService->search(
    'red sho',
    filters: ['tenant' => 42, 'type' => ['product', 'article']],
    sort: SearchSort::Relevance, // or RelevanceWithRecency, Newest, Oldest
    page: 1,
    hydrate: true,
);

foreach ($result->hits as $hit) {
    $hit->entity; // your Product
}

$result->entities(); // or just the Products

$result->total;
$result->hasNextPage;

Every word has to match the start of a word somewhere in the text, so red sho finds "Red running shoes". Values of the same filter are OR, different filters are AND

The index doesn't update itself, call SearchIndexer::index(), indexByIds() or remove() or rerun the command when your entities change

Translations

If an entity should be found in multiple languages, return one document per language instead of using the attributes:

#[SearchableDocuments]
public function searchDocuments(): iterable
{
    yield Document::create('en')
        ->withText($this->name, Weight::Highest)
        ->withFilter('lang', 'en');

    yield Document::create('de')
        ->withText($this->nameGerman, Weight::Highest)
        ->withFilter('lang', 'de');
}

Search with filters: ['lang' => 'de'] and $hit->variant tells you which one matched

License

MIT