PHPackages                             emhar/search-doctrine-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. emhar/search-doctrine-bundle

ActiveSymfony-bundle

emhar/search-doctrine-bundle
============================

Simple way to create a search service in tiny web sites. It works without search engine, just with Doctrine ORM.

0445PHP

Since Aug 23Pushed 11y ago1 watchersCompare

[ Source](https://github.com/emhar/SearchDoctrineBundle)[ Packagist](https://packagist.org/packages/emhar/search-doctrine-bundle)[ RSS](/packages/emhar-search-doctrine-bundle/feed)WikiDiscussions master Synced today

READMEChangelogDependenciesVersions (1)Used By (0)

Search Doctrine Bundle
======================

[](#search-doctrine-bundle)

What is SearchDoctrineBundle ?
------------------------------

[](#what-is-searchdoctrinebundle-)

Simple way to create a search service in tiny web sites. It works without search engine, just with Doctrine ORM. Describe your result with a simple PHP class, bind it with annotations to your Doctrine entities.

This Symfony2 Bundle provide a service that generate a search Form, results and page count. Result objects are ordered by score, calculated with requested word weights in hits.

[![Latest Stable Version](https://camo.githubusercontent.com/aa77537b8e296af7b91910070ac71eb291a612c4963e10909c1f34ebd2129b23/68747470733a2f2f706f7365722e707567782e6f72672f656d6861722f7365617263682d646f637472696e652d62756e646c652f762f737461626c652e737667)](https://packagist.org/packages/emhar/search-doctrine-bundle)[![Latest Unstable Version](https://camo.githubusercontent.com/87d7d9978f1ee760fa4282488aca87416a630d78add0269c5e0596b51c389699/68747470733a2f2f706f7365722e707567782e6f72672f656d6861722f7365617263682d646f637472696e652d62756e646c652f762f756e737461626c652e737667)](https://packagist.org/packages/emhar/search-doctrine-bundle)[![License](https://camo.githubusercontent.com/b73d23c9c10b1571343621994f4cfc88e6b56ab2ade0c8559ebc466707a038af/68747470733a2f2f706f7365722e707567782e6f72672f656d6861722f7365617263682d646f637472696e652d62756e646c652f6c6963656e73652e737667)](https://packagist.org/packages/emhar/search-doctrine-bundle)[![Total Downloads](https://camo.githubusercontent.com/36ed5ab717d14110b82d6c763d5025a5b072bbcc7a38d2dc067869f57501d0fe/68747470733a2f2f706f7365722e707567782e6f72672f656d6861722f7365617263682d646f637472696e652d62756e646c652f646f776e6c6f6164732e737667)](https://packagist.org/packages/emhar/search-doctrine-bundle)[![Build Status](https://camo.githubusercontent.com/51336c874522938317e781fdbdd62501ac85f01740d966d3a23b78fa873c9e52/68747470733a2f2f7472617669732d63692e6f72672f656d6861722f536561726368446f637472696e6542756e646c652e7376673f6272616e63683d6d6173746572)](https://travis-ci.org/emhar/SearchDoctrineBundle)

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

[](#installation)

### Composer

[](#composer)

Add the following dependencies to your projects composer.json file:

```
"require": {
    # ..
    "emhar/search-doctrine-bundle": "dev-master"
    # ..
}

```

You have to enable the bundle in your AppKernel.php :

```
// app/AppKernel.php
public function registerBundles()
{
    return array(
        //...
			new Emhar\SearchDoctrineBundle\EmharSearchDoctrineBundle(),
		//...
    );
}
```

Usage
-----

[](#usage)

### Describe a Search Item

[](#describe-a-search-item)

```
//...

use Emhar\SearchDoctrineBundle\Item\AbstractItem;
use Emhar\SearchDoctrineBundle\Mapping\Annotation\Hit;
use Emhar\SearchDoctrineBundle\Mapping\Annotation\ItemEntity;

/**
 * @ItemEntity(
 *	identifier="artist",
 *  label="My Artists",
 *  entityClass="MyBundle\Entity\Artist"
 * )
 * @ItemEntity(
 *	identifier="album",
 *  label="My Albums",
 *  entityClass="MyBundle\Entity\Album"
 * )
 */
class MyItem extends AbstractItem
{

	//...

	/**
	 * Construct Resource
	 *
	 * @Hit(identifier="id", scoreFactor=0, sortable=false, label="ID", mapping={
	 * 	"album"="id",
	 * 	"artist"="id"
	 * })
	 * @Hit(identifier="name", scoreFactor=3, sortable=false, label="Name", mapping={
	 * 	"album""name",
	 * 	"artist""name"
	 * })
	 */
	public function __construct($id, $name, $score, $type)
	{
		//...
	}

	//...
}
```

### Call service to get form, results and page count

[](#call-service-to-get-form-results-and-page-count)

```
//...
use ...\Resource;
//...
$searchService = $this->get('emhar_search_doctrine.search_service');
/* @var $searchService \Emhar\SearchDoctrineBundle\Services\SearchService */
$form = $searchService->getForm(MyItem::getClass(), $this->generateUrl('...'));
$form->handleRequest($this->getRequest());
if ($form->isValid())
{
	$items = $searchService->getResults(MyItem::getClass(), $form, $page);
	$pageCount = $searchService->getPageCount(MyItem::getClass(), $form);
}
//...
```

> You must provide an action URI to `getForm` method

### ItemEntity annotation

[](#itementity-annotation)

```
/**
 * @ItemEntity(
 *	identifier="album",
 *  label="My Albums",
 *  entityClass="MyBundle\Entity\Album"
 * )
 */
```

- **identifier**: an identifier of your choice `string` `required`
- **label**: Entity label, will be used in form `string` `required`
- **entityClass**: Entity class, must be a valid doctrine entity `string` `required`

### Hit annotation

[](#hit-annotation)

```
/**
 * @Hit(identifier="id", scoreFactor=0, sortable=false, label="ID" mapping={
 * 	"album"="id",
 * 	"artist"="id"
 * })
 */
```

- **identifier**: constructor parameter `string` `required`
- **scoreFactor**: hit factor in score `int` `default 1`
- **sortable**: boolean, determine if hit is sortable `bool` `default false`, currently not supported
- **label**: label for this hit `string` `required`
- **mapping key**: entity identifier from SearchItem annotation `string`
- **mapping value**: entity attribute name `string` `required`

### Several types, string conversion

[](#several-types-string-conversion)

If a hit has several types depending on the entities, returns depending on type :

- result casted as string
- empty string.

```
/**
 * @Hit(identifier="id", scoreFactor=0, sortable=false, label="ID", mapping={
 * 	"album"="id",
 * 	"artist"="name"
 * })
 */
```

### Omit some entities

[](#omit-some-entities)

You can omit some entities in the hit definitions, returns null value.

```
/**
 * @Hit(identifier="id", scoreFactor=0, sortable=false, label="ID", mapping={
 * 	"album"="id",
 * 	"artist"="id"
 * })
 * @Hit(identifier="name", scoreFactor=3, sortable=false, label="Name", mapping={
 * 	"album"="name"
 * })
 */
```

### Chain getter, **n**ToOne relation

[](#chain-getter-ntoone-relation)

You can chain getters for **n**ToOne relations, implode attribute names by points.

```
/**
 * @Hit(identifier="ownerName", scoreFactor=2, sortable=false, label="Owner Name", mapping={
 * 	"album"="artist.name",
 * 	"track"="album.artist.name"
 * })
 */
```

> **Waring**: Chained getters duplicates results in **n**ToMany relations.

### Get score and entity identifier

[](#get-score-and-entity-identifier)

If you name an item constructor parameter :

- **score**: receive the item score, calculate with the character number that match with request text
- **type**: receive the entity identifier, useful to recognize from where the result comes and maybe generate different URL...

```
//...
/**
 * Construct Resource
 *
 * @Hit(identifier="id", scoreFactor=0, sortable=false, label="ID", mapping={
 * 	"album"="id",
 * 	"artist"="id"
 * })
 * @Hit(identifier="name", scoreFactor=3, sortable=false, label="Name", mapping={
 * 	"album""name",
 * 	"artist""name"
 * })
 */
public function __construct($id, $name, $score, $type)
{
	//...
}
//...
```

Or omit them if you do not need

```
//...
/**
 * Construct Resource
 *
 * @Hit(identifier="id", scoreFactor=0, sortable=false, label="ID", mapping={
 * 	"album"="id",
 * 	"artist"="id"
 * })
 * @Hit(identifier="name", scoreFactor=3, sortable=false, label="Name", mapping={
 * 	"album""name",
 * 	"artist""name"
 * })
 */
public function __construct($id, $name)
{
	//...
}
//...
```

###  Health Score

22

—

LowBetter than 22% of packages

Maintenance20

Infrequent updates — may be unmaintained

Popularity12

Limited adoption so far

Community7

Small or concentrated contributor base

Maturity41

Maturing project, gaining track record

 Bus Factor1

Top contributor holds 100% of commits — single point of failure

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.

### Community

Maintainers

![](https://www.gravatar.com/avatar/083980c26476181b2efc6fd224be64708dbd177d816c0c7efea3de5f427ae3e0?d=identicon)[emhar](/maintainers/emhar)

---

Top Contributors

[![emhar](https://avatars.githubusercontent.com/u/7818042?v=4)](https://github.com/emhar "emhar (12 commits)")

### Embed Badge

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

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

PHPackages © 2026

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