PHPackages                             becklyn/search-bundle - PHPackages - PHPackages  [Skip to content](#main-content)[PHPackages](/)[Directory](/)[Categories](/categories)[Trending](/trending)[Leaderboard](/leaderboard)[Changelog](/changelog)[Analyze](/analyze)[Collections](/collections)[Log in](/login)[Sign up](/register)

1. [Directory](/)
2. /
3. [Search &amp; Filtering](/categories/search)
4. /
5. becklyn/search-bundle

ActiveSymfony-bundle[Search &amp; Filtering](/categories/search)

becklyn/search-bundle
=====================

Simply and automatically power your Symfony projects with Elasticsearch.

2.0.0(3y ago)69954[3 issues](https://github.com/Becklyn/SearchBundle/issues)BSD-3-ClausePHPPHP &gt;=8.1

Since Dec 30Pushed 3y ago2 watchersCompare

[ Source](https://github.com/Becklyn/SearchBundle)[ Packagist](https://packagist.org/packages/becklyn/search-bundle)[ Docs](https://github.com/Becklyn/SearchBundle)[ RSS](/packages/becklyn-search-bundle/feed)WikiDiscussions master Synced 2d ago

READMEChangelog (8)Dependencies (12)Versions (9)Used By (0)

Search Bundle
=============

[](#search-bundle)

Installation
------------

[](#installation)

1. First install the bundle via composer:

    ```
    composer require becklyn/search-bundle
    ```
2. Load the bundle in your `AppKernel`

Configuration
-------------

[](#configuration)

### Entity annotations

[](#entity-annotations)

#### Marking a class for indexing

[](#marking-a-class-for-indexing)

For regular entities just mark the class with the annotation and implement the `SearchableEntityInterface` interface:

```
use Becklyn\SearchBundle\Entity\SearchableEntityInterface;
use Becklyn\SearchBundle\Mapping as Search;

/**
 * @Search\Item()
 */
class SomeEntity implements SearchableEntityInterface
{
}
```

For localized entities, mark the class and implement the `LocalizedSearchableEntityInterface` interface:

```
use Becklyn\Interfaces\LanguageInterface;
use Becklyn\SearchBundle\Entity\LocalizedSearchableEntityInterface;
use Becklyn\SearchBundle\Mapping as Search;

/**
 * @Search\Item(
 *   index="custom-index-name",
 *   loader="some.service:method",
 * )
 */
class LocalizedSomeEntity implements LocalizedSearchableEntityInterface
{
    /**
     * @return LanguageInterface
     */
    public function getLanguage ()
    {

    }
}
```

Note: you will need the `LanguageInterface` from the [`becklyn/interfaces`](https://github.com/Becklyn/Interfaces) package.

#### `@Search\Item()` annotation

[](#searchitem-annotation)

```
/**
 * @Search\Item(
 *   index="custom-index-name",
 *   loader="some.service:method",
 * )
 */
```

PropertyDescription`index`The name of the index. If none is given, the name is automatically generated from the FQCN of the class.`loader`The custom entity loader. Please refer to the chapter about entity loaders to [learn more](#entity-loader).`autoIndex`(Default `true`) Whether the searchable item should be indexed automatically whenever it's persisted or updated in Doctrine. [Learn more](#disabling-automatic-indexing)### Marking a field / getter for indexing

[](#marking-a-field--getter-for-indexing)

```
use Becklyn\SearchBundle\Mapping as Search;

class SomeEntity
{
    /**
     * @Search\Field()
     */
    private $headline;

    /**
     * @Search\Field()
     */
    public function getSomeData ()
    {
    }
}
```

Please note that a `protected` / `private` property `test` needs to have a way to access it, either via getter `getTest()`, isser `isTest()` or hasser `hasTest()`.

#### `@Search\Field()` annotation

[](#searchfield-annotation)

```
/**
 * @Search\Field(
 *   weight=1,
 *   fragments=null,
 *   format="plain",
 * )
 */
```

PropertyDescription`weight`The value with which this field is boosted when searching.`fragments`The number of highlight fragments returned when searching. `null` returns the complete text of the hit.`format`The format of this field. Defines which `format_processor` is used to manipulate the property/getter value.### App configuration

[](#app-configuration)

The config belongs in `app/config.yml`.

A full configuration example:

```
becklyn_search:
    server: "127.0.0.1:9200"
    index: "app-index-{language}"
    format_processors:
        html: "app.content.renderer"            # short version
        pdf:                                    # full version
            service: "pdf.ocr.text_extractor"
            html_post_process: true
    analyzers:
        analyzer_en:
            tokenizer: lowercase
            filter:
                - standard
                - lowercase
                - stemmer_en
                - asciifolding
                - default_filter_shingle
            char_filter:
                - filter_1
                - filter_2
    filters:
        stemmer_en:
            type: stemmer
            name: english
    unlocalized:
        analyzer: analyzer_default # a string value means that both index and search use the same analyzer
    localized:
        de:
            analyzer:
                index: analyzer_en
                search: analyzer_en
```

KeyDescription`server`(**required**) The DSN to connect to the server.`index`(**required**) The pattern with which the index names are generated. The `{language}` placeholder must be included and will be replace with the language code.`format_processors`Processors for different text formats. If a field with a given processor is indexed, the processor is called and `html_post_process`ed, if it is selected. This will clean up the HTML (a better version of `strip_tags`), so that the processor can transform the format to HTML (and have it transformed to plain text afterwards). Default for `html_post_process` is `false`.`analyzers`A list of custom analyzers. The syntax mirrors the Elasticsearch API.`filters`A list of custom filters. The syntax mirrors the Elasticsearch API.`unlocalized`The definition for all unlocalized entities. Currently only the selection of custom analyzers is possible.`localized`The configuration for localized entities in every language. Currently only the selection of custom analyzers is possible.Usage
-----

[](#usage)

### Searching

[](#searching)

Just get the `becklyn.search.client` service and search with it:

```
$searchResult = $this->get("becklyn.search.client")->search(
    string $query,
    LanguageInterface $language = null,
    array $itemClasses = [],
    array $filters = []
);
```

The method has three parameters:

ArgumentTypeDescription`query``string`The query string to search for.`language``LanguageInterfacenull``itemClasses``string[]`The FQCN of the entities, that should be searched. If no explicit entity class is given, all (indexed) entities are searched.`filters``string[]`The filter values. See the chapter about Filtering for details.### Indexing

[](#indexing)

You can either index an entity manually via a CLI command, by calling a concrete service, or automatically by using the built-in doctrine event listeners.

#### Automatic indexing

[](#automatic-indexing)

Doctrine-managed entities are by default automatically indexed upon persistence/updating due to an built-in doctrine lifecycle event listener.

#### Disabling automatic indexing

[](#disabling-automatic-indexing)

The `Becklyn\SearchBundle\Mapping\Item` annotation allows you to configure how a search item is indexed. By default annotated classes will be indexed automatically whenever it's persisted or updated in Doctrine.

For use cases where you don't want your entities to be indexed immediatelly, e.g. when it needs further processing, you can set `Becklyn\SearchBundle\Mapping\Item#autoIndex` to `false`. This will force the Doctrine lifecycle handler to skip the automatic index update for this entity.

**Warning** This shifts the responsibility of indexing an entity from the bundle's code into the application's code by invoking the `becklyn.search.indexer`.

```
$this->get("becklyn.search.indexer")->index(SearchableEntityInterface $entity);
```

Or by running the Symfony CLI `becklyn:search:index` command. The index command isn't affected by this option.

#### Manual indexing

[](#manual-indexing)

#### CLI command indexing

[](#cli-command-indexing)

To (re-)index your entities from the CLI, the `becklyn/search-bundle` exposes the `becklyn:search:index` command. For more commands please see the [CLI commands](#cli-commands) section.

The `becklyn:search:index` command indexes *all* entities irregardless of the `autoIndex` setting.

#### Programatic indexing

[](#programatic-indexing)

If you want to index programatically, just retrieve an instance of the `becklyn.search.indexer` service and call the `index` method:

```
$this->get("becklyn.search.indexer")->index(SearchableEntityInterface $entity);
```

#### Modifying the indexed data

[](#modifying-the-indexed-data)

The indexed data can be modified by listening to the `"becklyn_search.index"` event (or `Becklyn\SearchBundle\Event\IndexEntityEvent::EVENT`).

Your listener receives an `Becklyn\SearchBundle\Event\IndexEntityEvent` with the already serialized data and the entity to serialize:

```
use Becklyn\SearchBundle\Event\IndexEntityEvent;

public function myEventListener (IndexEntityEvent $event)
{
    $data = $event->getData();
    $entity = $event->getEntity();

    if (42 === $entity->getId())
    {
        $data["property-headline"] = "The answer to everything.";
        $event->setData($data);
    }
}
```

For now, the listener has to know the internal field name, unfortunately. This will be improved in a future version.

Entity Loader
-------------

[](#entity-loader)

A search item can define a custom entity loader:

```
use Becklyn\SearchBundle\Mapping as Search;

/**
 * @Search\Item(loader="custom.service:method")
 */
class Example
{
}
```

If a custom loader is defined, the service is fetched and the method called. The loader syntax translates to a call like this:

```
/**
 * @Search\Item(loader="custom.service:method")
 */

// --> will load the entities using
$container->get("custom.service")->method(int[] $ids = null);
```

The method must have an optional array parameter. If the loader is called with `null`, all entities should be returned. If the loader is called with `int[]`, only the entities with an id in the `int` array have to be loaded.

It is not required to load entities for *all* provided ids, as the missing search results will just be removed from the result list.

The loader **must** return an `EntityLoaderResult`.

Filtering
---------

[](#filtering)

In some cases the searched items should be filtered by a field other than the language.

```
use Becklyn\SearchBundle\Mapping as Search;

class SomeClass
{
    /**
     * @Search\Filter("filter")
     */
    public $property;

    /**
     * @Search\Filter("another-filter")
     */
    public function method ()
    {
        // ...
    }
}
```

The annotation has a single required attribute: the name of the filter. This name needs to be unique across the app.

When searching, you can filter for hits with this specific filter values like this:

```
$searchResult = $this->get("becklyn.search.client")->search(
    "some search text",
    $english,
    [],
    [
        "filter" => "value",
        "another-filter" => "another value",
    ]
);
```

CLI Commands
------------

[](#cli-commands)

The bundle exposes multiple CLI commands.

CommandDescription`becklyn:search:client`Search directly from the CLI`becklyn:search:debug`Shows various debug output and tests connection to the ElasticSearch`becklyn:search:index`(Re-)indexes all entities`becklyn:search:metadata`(Re-)generates and caches entity metadataFor additional parameters and options for each command, please directly consult the commands help, e.g. `php bin/console becklyn:search:client --help`.

###  Health Score

34

—

LowBetter than 75% of packages

Maintenance10

Infrequent updates — may be unmaintained

Popularity21

Limited adoption so far

Community16

Small or concentrated contributor base

Maturity77

Established project with proven stability

 Bus Factor2

2 contributors hold 50%+ of commits

How is this calculated?**Maintenance (25%)** — Last commit recency, latest release date, and issue-to-star ratio. Uses a 2-year decay window.

**Popularity (30%)** — Total and monthly downloads, GitHub stars, and forks. Logarithmic scaling prevents top-heavy scores.

**Community (15%)** — Contributors, dependents, forks, watchers, and maintainers. Measures real ecosystem engagement.

**Maturity (30%)** — Project age, version count, PHP version support, and release stability.

###  Release Activity

Cadence

Every ~362 days

Recently: every ~543 days

Total

7

Last Release

1297d ago

Major Versions

1.2.1 → 2.0.02022-12-12

PHP version history (2 changes)1.0.0-beta.1PHP ^7.0

2.0.0PHP &gt;=8.1

### Community

Maintainers

![](https://avatars.githubusercontent.com/u/1044355?v=4)[Becklyn Studios](/maintainers/becklyn)[@Becklyn](https://github.com/Becklyn)

---

Top Contributors

[![apfelbox](https://avatars.githubusercontent.com/u/1032411?v=4)](https://github.com/apfelbox "apfelbox (7 commits)")[![mangoischke](https://avatars.githubusercontent.com/u/22484446?v=4)](https://github.com/mangoischke "mangoischke (7 commits)")[![tkasper](https://avatars.githubusercontent.com/u/1580938?v=4)](https://github.com/tkasper "tkasper (4 commits)")[![keichinger](https://avatars.githubusercontent.com/u/439899?v=4)](https://github.com/keichinger "keichinger (2 commits)")[![lukasbrodbeck](https://avatars.githubusercontent.com/u/12810590?v=4)](https://github.com/lukasbrodbeck "lukasbrodbeck (1 commits)")[![Thyrannoizer](https://avatars.githubusercontent.com/u/29758676?v=4)](https://github.com/Thyrannoizer "Thyrannoizer (1 commits)")

---

Tags

bundleelasticsearchphpsymfonysymfony-bundle

### Embed Badge

![Health badge](/badges/becklyn-search-bundle/health.svg)

```
[![Health](https://phpackages.com/badges/becklyn-search-bundle/health.svg)](https://phpackages.com/packages/becklyn-search-bundle)
```

###  Alternatives

[easycorp/easyadmin-bundle

Admin generator for Symfony applications

4.3k17.9M380](/packages/easycorp-easyadmin-bundle)[open-dxp/opendxp

Content &amp; Product Management Framework (CMS/PIM)

9421.6k59](/packages/open-dxp-opendxp)[sylius/sylius

E-Commerce platform for PHP, based on Symfony framework.

8.5k5.9M723](/packages/sylius-sylius)[pimcore/pimcore

Content &amp; Product Management Framework (CMS/PIM/E-Commerce)

3.8k3.8M495](/packages/pimcore-pimcore)[2lenet/crudit-bundle

The easy like Crud'it Bundle.

1616.4k12](/packages/2lenet-crudit-bundle)[oro/platform

Business Application Platform (BAP)

645143.5k114](/packages/oro-platform)

PHPackages © 2026

[Directory](/)[Categories](/categories)[Trending](/trending)[Changelog](/changelog)[Analyze](/analyze)
