Weave Code
Weaver
Helps Laravel developers discover, compare, and choose open-source packages. See popularity, security, maintainers, and scores at a glance to make better decisions.
Feedback
Share your thoughts, report bugs, or suggest improvements.
Subject
Message

Search Laravel Package

ibexa/search

Ibexa Search provides the search engine integration layer for Ibexa DXP and Ibexa Open Source, powering content queries and indexing. Commercial use requires an Ibexa DXP subscription; GPLv2 otherwise.

View on GitHub
Deep Wiki
Context7

Getting Started

ibexa/search is not a standalone search library you reach for on a greenfield project — it is the search integration layer that ships with Ibexa DXP / Ibexa Open Source. In practice you consume it through the platform's SearchService and the search UI it wires up, not by calling classes from this package directly.

Minimal setup

  1. Install the platform, not this package: composer require ibexa/oss (or ibexa/dxp), which pulls ibexa/search in lockstep with the rest of the release train. Confirm with composer show ibexa/search.
  2. Match versions deliberately. The 5.x line requires PHP 8.3+ and Symfony 7; the 4.6.x line is the LTS branch for older stacks. Do not mix a 5.x search package into a 4.x application.
  3. Configure a real search backend (Solr or Elasticsearch) in your environment; then run bin/console ibexa:reindex.

Where to look first

  • The README is a stub — it points at https://doc.ibexa.co/. Budget time for the official docs; there is nothing useful in-repo for onboarding.
  • vendor/ibexa/search/src and the bundle's Resources/config/*.yaml — that is where the service tags and extension points actually live.
  • The release notes in this repo are the most reliable changelog for behavioral changes in search (suggestions, facets, date criteria).

First use case: run a query

Start with the public API rather than package internals:

use Ibexa\Contracts\Core\Repository\Values\Content\Query;
use Ibexa\Contracts\Core\Repository\Values\Content\Query\Criterion;
use Ibexa\Contracts\Core\Repository\Values\Content\Query\SortClause;

$query = new Query();
$query->query  = new Criterion\FullText('running shoes');
$query->filter = new Criterion\ContentTypeIdentifier(['product']);
$query->sortClauses = [new SortClause\ContentName(Query::SORT_ASC)];
$query->limit  = 20;
$query->offset = 0;

$result = $this->searchService->findContent($query);

Once that works, move to the higher-level features this package owns: aggregations (facets), user-selectable sorting, the autocomplete/suggestion endpoint, and spellcheck.

Implementation Patterns

Query composition Build queries from Criterion leaves plus LogicalAnd / LogicalOr / LogicalNot composites. Keep the full-text criterion separate from structural filters (ContentTypeIdentifier, SectionId, ParentLocationId, Visibility) so the backend can cache and rank efficiently. Set $query->performCount only when you actually need a total — it is the expensive part on large indexes.

Facets / aggregations Facets are declared on the query as aggregations and read back from the search result; the UI layer renders them as term/range filters. The workflow that holds up:

  1. Declare the aggregation(s) on the Query.
  2. Read FacetResult entries off the result and map them to your filter form.
  3. Apply the selected facet values as Criterion entries on the next query.
  4. Keep the facet definition and the criterion it maps to in one class — drift between the two is the most common bug here.

Sorting Ibexa's UI sorting (added in 5.0) only exposes sorts you allowlist. Implement it as a small resolver: take a request parameter, validate against an enum of allowed sort clauses, and default to relevance. Always append a stable tie-breaker (SortClause\ContentId) so pagination does not shuffle equal-ranked documents between pages. Date sorts should use DatePublished / DateModified explicitly rather than a generic Field sort on a date attribute.

Autocomplete / suggestions The suggestion endpoint returns autocomplete candidates plus the total result count (the count was added for the suggestions endpoint in the 4.6/5.0 line). Treat it as a separate, cheap query path:

  • Debounce on the client, cache per normalized prefix for ~60s server-side.
  • Do not reuse the full search query builder for suggestions; tokenization and field boosts differ.
  • Expect whole-word matching only. Partial-word suggestion matching was deliberately removed, so the prefix must resolve to a real term.

Result mapping If you need to reshape hits into view models (badges, highlighted snippets, pager rows), the PagerSearchDataMapper contract introduced in 5.0 is the intended seam. Implementing it keeps presentation logic out of templates and out of your controllers.

Extending the backend translation When you need a criterion the platform does not support, add a criterion visitor and register it as a tagged service (check the bundle YAML for the exact tag name in your version). The same pattern applies to sort clause visitors and aggregation visitors. This is the only supported way to teach the search backend about a new query shape — do not hand-build backend query strings from application code.

Keep queries behind a service Inject SearchService into a dedicated ProductSearch / ArticleSearch class, not into controllers. You get one place to add caching, logging, and permission reasoning, and one place to swap in a fake for tests.

Gotchas and Tips

  • The license is the first thing to check. The repo reports NOASSERTION because the code is dual-licensed: Ibexa Business Use License (requires a DXP subscription) and GPLv2. Decide which applies to you before forking or vendoring; GPLv2 is copyleft and the BUL requires a paid subscription. Get this signed off early, not at release time.
  • Documentation is external and thin. Nothing in this repository explains the feature set. Anything you learn must be captured in your own notes or you will re-learn it every upgrade.
  • Version alignment is non-negotiable. 5.0 removed the class_alias BC layer, renamed domains, required PHP 8.3/Symfony 6→7, and introduced PagerSearchDataMapper. If you are on 4.x, stay on the 4.6 LTS branch; do not cherry-pick 5.x behavior.
  • Zero results usually means permissions or a stale index. Search results are filtered by the content permission model, so a query that looks correct can legitimately return nothing for a given user. Reindex (bin/console ibexa:reindex) and clear cache after content type or field configuration changes before debugging PHP.
  • FullText is broader than you think. A fix in the 5.0 line addressed the criterion matching all text fields. If precision matters, prefer explicit field criteria and treat FullText as a relevance-scored catch-all.
  • Date range criteria had a real bug (adjusted in 4.6.22). If you support date filtering, test boundary values and timezones explicitly rather than trusting the default builder.
  • Facet and selector defaults changed between releases ("All" placeholder for dropdowns, "Choose an option" for the language selector, and "Top Level Nodes" removed from suggestion breadcrumbs). Any UI test asserting on placeholder text will break on upgrade.
  • Release cadence is quiet — many releases are literally "No significant changes." Pin exact versions, read the tag-to-tag diff when you bump, and do not track a dev branch expecting activity.
  • Debugging the actual backend query is done at the search engine layer (Solr/Elasticsearch logs), not in PHP. Enable query logging in the backend when a criterion behaves unexpectedly; the visitor output is far more informative than the repository result object.
  • Extension points are all tagged services. Before writing custom code, grep the bundle's Resources/config for tags — criterion visitors, sort visitors, aggregation visitors, and mappers are usually already wired and just need your class registered.
Weaver

How can I help you explore Laravel packages today?

Conversation history is not saved when not logged in.
Prompt
Add packages to context
No packages found.
ably/pubsub-server
mstfkhazaal/defender
mfonte/base62x
karnoweb/metapilot
tobya/bcsapiwrapper
swalker2/cpanel
vish4395/laravel-translation-manager
morningtrain/economic
teksite/systeminfo-laravel
atomcms/voting
run6/weather
siokas/laravelembeddirectives
adamlien/pkuuids
gilsonsouza/lara-doc-generator
manelgavalda/enrollment_mobile
unabomber/timezone
delatbabel/contacts
astritzeqiri/g-recaptcha
kevinongko/laravel-genode
developeruz/laravel-analytics