PHPackages                             neoslive/hybridsearch - 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. neoslive/hybridsearch

ActiveNeos-package[Search &amp; Filtering](/categories/search)

neoslive/hybridsearch
=====================

Add description here

1.1.44(8y ago)86171JavaScript

Since Nov 20Pushed 8y ago1 watchersCompare

[ Source](https://github.com/miegli/Neoslive.Hybridsearch)[ Packagist](https://packagist.org/packages/neoslive/hybridsearch)[ RSS](/packages/neoslive-hybridsearch/feed)WikiDiscussions master Synced 2mo ago

READMEChangelog (10)Dependencies (6)Versions (72)Used By (1)

HybridSearch
============

[](#hybridsearch)

HybridSearch is a powerful realtime search engine written in Javascript/AngularJS based on an intelligent indexing mechanism powered by [Google Firebase](http://firebase.google.com/) (noSQL). Hybrid stands for the innovative way of streaming search results. Every search request delivers small and preselected data blocks and then they are processed client side for calculation the search result. Whenever data of the source application (Neos CMS, Magento, etc.) was changed, HybridSearch updates the search index und performs a live update of current search results - that's why we call it realtime search engine. The search engine was invented by [Michael Egli](http://www.assoftware.ch) in 2016 and it's a free open source software. Special thanks to Oliver Nightingale ([lunr.js](https://github.com/olivernn/lunr.js/)) and Wei Song ([elasticlunr.js](https://github.com/weixsong/elasticlunr.js)).

Features
--------

[](#features)

- **Search as you type** (autocomplete and autocorrect were done in background).
- **Realtime binding** (search index and results view).
- Analyzes Google Analytics Reports for **better semantics** (optionally).
- Creates search index from rendered and structured data, not just from raw data.
- No configuration needed while indexing.
- **Provides a javascript framework for creating fantastic user experience**.
- Minimal, but **powerful configurations** (relevance boosting, filtering, distincts, facets, etc.)
- **High performance**, no Server-side utilization while searching and very low cpu usage while indexing.
- Supports up to 100'000 concurrency search request. To reach 100,000 concurrent search requests, you usually first need to accumulate tens of millions of daily actives

Demo / Show case
----------------

[](#demo--show-case)

-  (Neos)

Implementations
---------------

[](#implementations)

HybridSearch comes with default integration for [Neos CMS](https://www.neos.io). Other implementations can be done very easy. Default Implementation for Magento is coming soon.

Installation with Neos
----------------------

[](#installation-with-neos)

### Backend

[](#backend)

#### Minimal configuration

[](#minimal-configuration)

`composer require neoslive/hybridsearch`

Create new a firebase project for [free](https://console.firebase.google.com/). Then you need a database token. Open your firebase project settings and create new database secret/token (see service accounts &gt; Database secrets).

Add to your flow Settings.yaml (minimal configuration)

```
Neoslive:
  Hybridsearch:
    Realtime: true
    Firebase:
      endpoint: 'https://** your firebase project name**.firebaseio.com/'
      token: '** your firebase token **'
    Filter:
      GrantParentNodeTypeFilter: '[instanceof TYPO3.Neos:Document]'
      ParentNodeTypeFilter: '[instanceof TYPO3.Neos:Node]'
      NodeTypeFilter: '[instanceof TYPO3.Neos:Content]'

```

#### Optimal configuration

[](#optimal-configuration)

Example of Settings.yaml

```
Neoslive:
  Hybridsearch:
    Realtime: true
    Firebase:
      endpoint: 'https://** your firebase project name**.firebaseio.com/'
      token: '** your firebase token **'
    Filter:
      GrantParentNodeTypeFilter: '[instanceof TYPO3.Neos:Document]'
      ParentNodeTypeFilter: '[instanceof TYPO3.Neos:Node]'
      NodeTypeFilter: '[instanceof Neoslive.Hybridsearch:Content]'
    TypoScriptPaths:
      page:
        Vendor.Package: neosliveHybridsearch
      breadcrumb:
        Vendor.Package: neosliveHybridsearchBreadcrumb

```

If you are using optimal configuration, then you need also something like following settings.

TypoScript (root.ts)

```
neosliveHybridsearch = TYPO3.TypoScript:Collection {
    collection = ${q(node)}
    itemName = 'node'
    itemRenderer = TYPO3.Neos:ContentCase
}

neosliveHybridsearchBreadcrumb = TYPO3.TypoScript:Collection {
    collection = ${q(node)}
    itemName = 'node'
    itemRenderer = Breadcrumb
}

```

NodeTypes.yaml

```
# Make your contact node searchable
'Vendor.Package:Contact:
  superTypes:
    'Neoslive.Hybridsearch:Content': TRUE

```

#### Indexing your data

[](#indexing-your-data)

Run flow command for initial indexing your Neos Site

`php ./flow hybridsearch:createfullindex`

For better semantic you should use optimal configuration and don't index all of your node types. The indexer is rendering every node as a standalone front-end view and not simple raw data, so initially it takes time. But the result is magic.

If you have set "Realtime: true", then all further changes are done automatically as an intelligent background job asynchronously and without any performance impacts while editing in Neos backend.

It's recommended to execute full index creating from time to time. Just create a cronjob like this one:

`1 1 * * 1 FLOW_CONTEXT=Production php -d memory_limit=8096M /home/www-data/flow hybridsearch:createfullindex >/dev/null 2>&1`

So, while your index is creating you should not waiting and do the frontend integration.

### Front-End

[](#front-end)

Add the following javascript files to your layout/template.

```

```

Create an Angular Controller.

```
.controller('searchCtrl', ['$scope', '$hybridsearch', '$hybridsearchObject', '$hybridsearchResultsObject', function ($scope, $hybridsearch, $hybridsearchObject, $hybridsearchResultsObject) {

// initialize scope vars
$scope.result = new $hybridsearchResultsObject();
$scope.query = '';

// initialize HybridSearch
var search = new $hybridsearchObject(
                new $hybridsearch(
                    'https://** your firebase project name**.firebaseio.com',
                    'live',
                    '** dimensionHash **',
                    '** nodename of the site'
        ));

// set search settings and run HybridSearch
search
.setQuery('query',$scope)
.$bind('result', $scope)
.run();

}]);

```

Create an HTML search page.

```

    Search:

    Results {{result.count()}}

         {{node.getProperty('title')}}
         {{node.getPreview()}}

```

HybridSearch own JavaScript Framework
-------------------------------------

[](#hybridsearch-own-javascript-framework)

HybridSearch provides a javascript framework for creating fantastic user experience. Create robust search-as-you-type, lists, facet-filters, etc. in minutes - and everything is wired to the realtime index without writing one line of code.

### Initializing

[](#initializing)

```
var hybridSearch = new $Hybridsearch(
 'https://.firebaseio.com',
 'live',
 'fb11fdde869d0a8fcfe00a2fd35c031d',
 'site-root-node-name'
));
var mySearch = new $HybridsearchObject(hybridSearch);

```

$HybridsearchObject (define the search request)
-----------------------------------------------

[](#hybridsearchobject-define-the-search-request)

This is the main request object, where all methods are called that are defining the search request.

Configuration methods
---------------------

[](#configuration-methods)

This methods are influencing the behavior of the search result.

### setNodeTypeLabels

[](#setnodetypelabels)

For each resulting nodeType the search engine creates a group name by the nodeType. So you can easy create facetted search results, etc.. With the method setNodeTypeLabels you are able to combine several nodeType groups into one.

##### Arguments

[](#arguments)

ParamTypeDetailsnodetypelabelsObjectset nodeType labels grouped result##### Returns

[](#returns)

{HybridsearchObject} the search object

##### Examples

[](#examples)

- `setNodeTypeLabels({'vendor-package-contact': 'Persons'},{'vendor-package-customers': 'Persons'})` group contact and customers into one group called "Persons".

---

### setPropertiesBoost

[](#setpropertiesboost)

Adjust the relevance score calculation for each nodeType property. Higher values means higher relevance score for matching properties.

##### Arguments

[](#arguments-1)

ParamTypeDetailsboostObjectAdjust the relevance score##### Returns

[](#returns-1)

{HybridsearchObject} the search object

##### Examples

[](#examples-1)

- `setPropertiesBoost({'vendor-package-contact-name': 50},{'vendor-package-contact-lastname': 50})` query matchings in lastname are higher scored in

---

### setParentNodeTypeBoostFactor

[](#setparentnodetypeboostfactor)

Adjust the relevance score calculation for each node by parent node type. The given boost value is the factor that is applied to the relavence score of each node.

##### Arguments

[](#arguments-2)

ParamTypeDetailsboostObjectAdjust the relevance score by given factor##### Returns

[](#returns-2)

{HybridsearchObject} the search object

##### Examples

[](#examples-2)

- `setParentNodeTypeBoostFactor({'typo3-neos-contentcollection1': 1.8,'typo3-neos-contentcollection2': 1.5})` nodes in parent node contentcollection1 are higher scored than nodes in contentcollection2

---

Filtering methods
-----------------

[](#filtering-methods)

This methods are restricting the search result.

### setQuery

[](#setquery)

Sets a query for the search. If scope is given, then threat the param as reference to the scopes variable and watch automatically for any changes. If param scope is undefined then search for the string itself.

##### Arguments

[](#arguments-3)

ParamTypeDetailsqueryStringquery search forscope (optional)Scopeangular scope##### Returns

[](#returns-3)

{HybridsearchObject} the search object

---

### setNodeType

[](#setnodetype)

Sets the nodeType (example 'vendor-package-contact'). If scope is given, then threat the param as reference to the scopes variable and watch automatically for any changes. If param scope is undefined then search for the string itself. NodeTypes are equivalent to Neos NodeTypes, but all special chars a replaced with '-' and everything is lowercase.

##### Arguments

[](#arguments-4)

ParamTypeDetailsnodeTypeStringrestrict search to given NodeTypescope (optional)Scopeangular scope##### Returns

[](#returns-4)

{HybridsearchObject} the search object

### addPropertyFilter

[](#addpropertyfilter)

Adds a property filter that restrict the search result. If scope is given, then threat the param as reference to the scopes variable and watch automatically for any changes. If param scope is undefined then search for the string itself.

##### Arguments

[](#arguments-5)

ParamTypeDetailspropertyStringname of the property to filtervalueString, ArrayLike, ObjectLikevalue(s) to filterscope (optional)Scopeangular scopeinverted (optional)booleantrue filter is invertedbooleanmode (optional)booleanfalse if all array values must match allnodeType (optional)stringapply filter only to given nodeType##### Returns

[](#returns-5)

{HybridsearchObject} the search object

##### Examples

[](#examples-3)

```
var persons = [
{'name':'michael','lastname': 'moor', primaryAdress: {'email': 'foo@bar.com'},secondaryAdress: {'email': 'foo@bar.com'}
{'name':'peter','lastname': 'moor', primaryAdress: {'email': 'peter@foo.com'},secondaryAdress: {'email': 'peter@bar.com'}
];

```

- `addPropertyFilter('persons.name',['michael','peter'])` finds persons with name 'michael' or 'peter'
- `addPropertyFilter('persons.name',{'michael': true,'peter': false})` finds persons with name 'michael' but not 'peter'
- `addPropertyFilter('persons.*.email','foo@bar.com')` finds persons with email '' in primary or secondary address.

### setNodePath

[](#setnodepath)

Sets the node path (or uri segment) that is the entry point searching for. If scope is given, then threat the param as reference to the scopes variable and watch automatically for any changes. If param scope is undefined then search for the string itself. NodeTypes are equivalent to Neos NodeTypes, but all special chars a replaced with '-' and everything is lowercase.

##### Arguments

[](#arguments-6)

ParamTypeDetailsnodePathStringrestrict search to given node pathscope (optional)Scopeangular scope##### Returns

[](#returns-6)

{HybridsearchObject} the search object

##### Examples

[](#examples-4)

- `setNodePath('/company/about/')` get only search results, that are under the uri path '/company/about/'

---

Preprocessing methods
---------------------

[](#preprocessing-methods)

This methods are called before the search filters are applied.

### addNodesByIdentifier

[](#addnodesbyidentifier)

Add nodes to local search index by given node identifiers (uuid). If the there are no further restrictions (filters), then the added nodes are added to the search result.

##### Arguments

[](#arguments-7)

ParamTypeDetailsnodesArrayadd nodes to search result##### Returns

[](#returns-7)

{HybridsearchObject} the search object

##### Examples

[](#examples-5)

- `addNodesByIdentifier(['64021902-b7d9-11e6-80f5-76304dec7eb7','57978ed3-6e41-48ce-8421-22d80beacef0'])` add the nodes to local search index.

---

Postprocessing methods
----------------------

[](#postprocessing-methods)

This methods are called after the search result was calculated.

### setOrderBy

[](#setorderby)

Sets orderings for the result. You can order the result in template view, but then you cannot use the limit/paginate method. Orderings are configured per nodeType or nodeTypeLabel. Ordering cannot be DESC because its an internal behavior of complex search algorithm.

##### Arguments

[](#arguments-8)

ParamTypeDetailsorderByObjectset orderings for each given nodeType or nodeTypeLabel##### Returns

[](#returns-8)

{HybridsearchObject} the search object

##### Examples

[](#examples-6)

- `setOrderBy({'vendor-package-contact': ['name','lastname']})` sorts result by name and lastname for contact nodes
- `setOrderBy({'*': 'title'})` sorts result by title for all other nodes

---

### setGroupedBy

[](#setgroupedby)

Group the result by given identifiers. With this groupedBy function you can filter out duplicates from the search result. GroupedBy are configured per nodeType or nodeTypeLabel.

##### Arguments

[](#arguments-9)

ParamTypeDetailsgroupByObjectset groupBy for each given nodeType or nodeTypeLabel##### Returns

[](#returns-9)

{HybridsearchObject} the search object

##### Examples

[](#examples-7)

- `setGroupedBy({'vendor-package-contact': ['name','lastname']})` group result by name and lastname for contact nodes. So only persons with different fullnames were applied to the search result.
- `setGroupedBy({'*': 'title'})` group result by title for all other nodes

---

Runtime methods
---------------

[](#runtime-methods)

This methods are called not more than once while initializing.

### $watch

[](#watch)

Watching the {HybridsearchResultsObject} for any changes.

##### Returns

[](#returns-10)

{HybridsearchObject} the search object

##### Examples

[](#examples-8)

- `$watch(function(data) {console.log(data);})` The function argument 'data' contains the current search result.

---

### $bind

[](#bind)

Bind the {HybridsearchResultsObject} to given scope variable.

##### Arguments

[](#arguments-10)

ParamTypeDetailsvariableStringscope variable name for binding toscopeScopeangular scope##### Returns

[](#returns-11)

{HybridsearchObject} the search object

##### Examples

[](#examples-9)

- `$bind('result',$scope)` The search result is automatically applied to the angular scope variable 'result', that you can use in your controller.

---

$HybridsearchResultsObject (define the search result)
-----------------------------------------------------

[](#hybridsearchresultsobject-define-the-search-result)

This is the main result object, where all methods are called that are presenting the search result.

Runtime methods
---------------

[](#runtime-methods-1)

### isLoading

[](#isloading)

Check if search is in progress. Return false when current search is done.

##### Returns

[](#returns-12)

{boolean} if search is done or not

##### Examples

[](#examples-10)

- `$scope.status = isLoading() ? 'please wait' : countAll()+' results found'`

---

Counter methods
---------------

[](#counter-methods)

The counter methods delivers statistics about current search result.

### count

[](#count)

Get number of nodes in current result (excluding turbo nodes)

##### Returns

[](#returns-13)

{Integer} number of nodes excluding turbonodes

##### Examples

[](#examples-11)

- `Results {{result.count()}}` where result is scope variable with binding to HybridsearchResultsObject (see $bind)

---

### countAll

[](#countall)

Get number of nodes in current result (including turbo nodes)

##### Returns

[](#returns-14)

{Integer} number of nodes including turbo nodes

---

### countTurboNodes

[](#countturbonodes)

Get number of turbo nodes nodes in current result

##### Returns

[](#returns-15)

{Integer} number of turbo nodes

---

### countByNodeType

[](#countbynodetype)

Get number of nodes in current result by node type

##### Arguments

[](#arguments-11)

ParamTypeDetailsnodeTypeStringnodeType##### Returns

[](#returns-16)

{Integer} number of nodes

---

### countByNodeTypeLabel

[](#countbynodetypelabel)

Get number of nodes in current result by node type label

##### Arguments

[](#arguments-12)

ParamTypeDetailsnodeTypeLabelStringnodeType label##### Returns

[](#returns-17)

{Integer} number of nodes

---

### getDistinctCount

[](#getdistinctcount)

Get number of different values (distinct) of current search result.

##### Arguments

[](#arguments-13)

ParamTypeDetailspropertyStringname of the property for distinct calculcation##### Returns

[](#returns-18)

{Integer} number of different values

Getter methods
--------------

[](#getter-methods)

The getter methods delivers the result as collection {HybridsearchResultsNode}.

### getNodes

[](#getnodes)

Get result collection (excluding turbo nodes)

##### Arguments

[](#arguments-14)

ParamTypeDetailslimit (optional)Integernumber of results##### Returns

[](#returns-19)

{Array} Collection of HybridsearchResultsNode

##### Examples

[](#examples-12)

- `{{node.getProperty('title')}}` where result is scope variable with binding to HybridsearchResultsObject (see $bind)

---

### getTurboNodes

[](#getturbonodes)

Get result collection (only turbo nodes)

##### Arguments

[](#arguments-15)

ParamTypeDetailslimit (optional)Integernumber of results##### Returns

[](#returns-20)

{Array} Collection of HybridsearchResultsNode

---

### getNodesByNodeType

[](#getnodesbynodetype)

Get result collection by node type

##### Arguments

[](#arguments-16)

ParamTypeDetailsnodeTypeStringnode type##### Returns

[](#returns-21)

{Array} Collection of HybridsearchResultsNode

---

### getNodesByNodeTypeLabel

[](#getnodesbynodetypelabel)

Get result collection by node type label

##### Arguments

[](#arguments-17)

ParamTypeDetailsnodeTypeStringnode type label##### Returns

[](#returns-22)

{Array} Collection of HybridsearchResultsNode

---

### getDistinct

[](#getdistinct)

Get distinct values of given property

##### Arguments

[](#arguments-18)

ParamTypeDetailspropertyStringname of the property for distinct calculcation##### Returns

[](#returns-23)

{Object.value} Value {Object.count} Number of nodes containing this value.

---

### getGrouped

[](#getgrouped)

Get alle nodes from current search result a grouped object.

##### Returns

[](#returns-24)

{HybridsearchResultsGroupObject} Result groups

##### Examples

[](#examples-13)

```

  {{group.getLabel()}} ({{group.count()}})

        {{node.getProperty('title')}}

```

Where result is scope variable with binding to HybridsearchResultsObject (see $bind)

---

$HybridsearchResultsGroupObject (define a group of result)
----------------------------------------------------------

[](#hybridsearchresultsgroupobject-define-a-group-of-result)

This object is representing a grouped result.

### count

[](#count-1)

Get number of items in group object

##### Returns

[](#returns-25)

{Integer} number of items

### getItems

[](#getitems)

Get group items as array

##### Returns

[](#returns-26)

{array} collection of {HybridsearchResultsDataObject}

---

$HybridsearchResultsDataObject (define a set of results)
--------------------------------------------------------

[](#hybridsearchresultsdataobject-define-a-set-of-results)

This object is representing a group of result items.

### count

[](#count-2)

Get number of items in this group

##### Returns

[](#returns-27)

{Integer} number of items

### getLabel

[](#getlabel)

Get groups label

##### Returns

[](#returns-28)

{String} label of group

### getNodes

[](#getnodes-1)

Get result collection (excluding turbo nodes)

##### Arguments

[](#arguments-19)

ParamTypeDetailslimit (optional)Integernumber of results##### Returns

[](#returns-29)

{Array} Collection of HybridsearchResultsNode

### getProperty

[](#getproperty)

Get value of first node in the group by given property. This is useful for getting values for grouped objects.

##### Arguments

[](#arguments-20)

ParamTypeDetailspropertyStringName of the property##### Returns

[](#returns-30)

{Mixed} Properties value

---

$HybridsearchResultsNode (define a single result item/node)
-----------------------------------------------------------

[](#hybridsearchresultsnode-define-a-single-result-itemnode)

This object is representing a single result item.

Getter methods
--------------

[](#getter-methods-1)

The getter methods delivers all informations about the item.

### getNodeType

[](#getnodetype)

Get the node type.

##### Returns

[](#returns-31)

{String} node type

---

### getScore

[](#getscore)

Get the relevance score of the items.

##### Returns

[](#returns-32)

{integer} relevance score (highest value is highest relevance)

---

### isTurboNode

[](#isturbonode)

Check if its a turbo node or a normal node.

##### Returns

[](#returns-33)

{boolean} true if is a turbo node, false is default node

---

### getBreadcrumb

[](#getbreadcrumb)

Get breadcrumb as HTML code (if its a document node).

##### Returns

[](#returns-34)

{String} HTML

---

### getUrl

[](#geturl)

Get Url (if its a document node).

##### Returns

[](#returns-35)

{String} url

---

### getPreview

[](#getpreview)

Get rendered preview of node.

##### Arguments

[](#arguments-21)

ParamTypeDetailsmaxlength (optional)Integermax. length of preview text##### Returns

[](#returns-36)

{String} preview content

---

### getSortingIndex

[](#getsortingindex)

Get sorting index of node.

##### Returns

[](#returns-37)

{Integer} sorting index value

---

### getProperty

[](#getproperty-1)

Get value by given property.

##### Arguments

[](#arguments-22)

ParamTypeDetailspropertyStringName of the property##### Returns

[](#returns-38)

{Mixed} Properties value

##### Examples

[](#examples-14)

- `{{node.getProperty('name')}}` return the name of mixed node types
- `{{node.getProperty('vendor-package-contact-name')}}` return only the name of node type vendor-package-contact
- `{{node.getProperty('primaryAdress.email')}}` return primary email
- `{{node.getProperty('*.email')}}` return all email addresses

---

### getDocumentNode

[](#getdocumentnode)

Get the nearest document node.

##### Returns

[](#returns-39)

{HybridsearchResultsNode} HybridsearchResultsNode containing breadcrumb and url

##### Examples

[](#examples-15)

```

    {{node.getDocumentNode().getProperty('title')}}
    Name: {node.getProperty('name')}}
    Lastname: {node.getProperty('lastname')}}

```

###  Health Score

36

—

LowBetter than 82% of packages

Maintenance20

Infrequent updates — may be unmaintained

Popularity19

Limited adoption so far

Community11

Small or concentrated contributor base

Maturity78

Established project with proven stability

 Bus Factor1

Top contributor holds 85.7% 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.

###  Release Activity

Cadence

Every ~3 days

Total

71

Last Release

3217d ago

### Community

Maintainers

![](https://www.gravatar.com/avatar/d953d53191e4a8d54da9423725a967f2785f5d47b656784d05291d949c6db098?d=identicon)[miegli](/maintainers/miegli)

---

Top Contributors

[![miegli](https://avatars.githubusercontent.com/u/743218?v=4)](https://github.com/miegli "miegli (6 commits)")[![samuelhauser](https://avatars.githubusercontent.com/u/1894064?v=4)](https://github.com/samuelhauser "samuelhauser (1 commits)")

### Embed Badge

![Health badge](/badges/neoslive-hybridsearch/health.svg)

```
[![Health](https://phpackages.com/badges/neoslive-hybridsearch/health.svg)](https://phpackages.com/packages/neoslive-hybridsearch)
```

###  Alternatives

[algolia/algoliasearch-magento-2

Algolia Search &amp; Discovery extension for Magento 2

1881.8M16](/packages/algolia-algoliasearch-magento-2)[algolia/search-bundle

Algolia Search integration for Symfony

1931.5M2](/packages/algolia-search-bundle)[studioespresso/craft-scout

Craft Scout provides a simple solution for adding full-text search to your entries. Scout will automatically keep your search indexes in sync with your entries.

80136.8k](/packages/studioespresso-craft-scout)[cmsig/seal-symfony-bundle

An integration of CMS-IG SEAL search abstraction into Symfony Framework.

15195.8k5](/packages/cmsig-seal-symfony-bundle)[open-dxp/opendxp

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

7310.3k29](/packages/open-dxp-opendxp)[wilr/silverstripe-algolia

Algolia Indexer and Search Functionality

1325.5k](/packages/wilr-silverstripe-algolia)

PHPackages © 2026

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