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

Ezfind Ls Laravel Package

ezsystems/ezfind-ls

Legacy eZ Publish extension for integrating Apache Solr search, enabling content indexing, faceted search, and multilingual search in older eZ Find-based installations.

View on GitHub
Deep Wiki
Context7

Getting Started

This is not a Laravel package — there is no service provider, no facade, no config/ezfind.php. ezsystems/ezfind-ls is the Composer-packaged form of the ezfind extension for eZ Publish legacy (4.x / 5.x legacy stack and the ezpublish-legacy bridge). Everything below assumes you are inside an existing eZ Publish legacy tree. If you are on a greenfield Laravel app, this package has nothing to offer you beyond reading its Solr schema as reference material.

Version matrix — pick your pin before anything else. As of v2017.12.0, the extension targets legacy 2017.10 or newer and PHP 7; it exists to carry the PHP 7 compatibility work that landed in that legacy release. If you are still on PHP 5.x with legacy 2015.x, you want the older 2015.01 line instead. Do not mix them: the 2017.12 branch assumes the legacy kernel's PHP 7 changes and the parent-constructor fixes it depends on.

Minimal path to a working search (assuming legacy 2017.10+):

  1. Prerequisites — a Solr 4.x server (match the version matrix for your eZ Find release; the bundled configset targets Solr 4.x), PHP 7.x with legacy 2017.10+, and either the solr PECL extension or the extension's HTTP fallback client.
  2. Install — composer require ezsystems/ezfind-ls:^2017.12 (pin explicitly; dev-master on this repo is not a moving target you want in production). The ezsystems/ezpublish-legacy-installer plugin places it under extension/ezfind. On a hand-rolled install, copy the directory there yourself.
  3. Enable — in settings/override/site.ini.append.php:
[ExtensionSettings]
ActiveExtensions[]=ezfind
  1. Regenerate autoloads and clear caches — this is the step people forget, and it matters more after an upgrade because class signatures changed:
php bin/php/ezpgenerateautoloads.php -o
php bin/php/ezcache.php --clear-all
# under the Symfony legacy bridge:
php bin/console ezpublish:legacy:script bin/php/ezpgenerateautoloads.php -o
  1. Point at Solr — settings/override/solr.ini.append.php:
[SolrServer]
SearchServerURI=http://127.0.0.1:8983/solr
  1. Create the core — php extension/ezfind/bin/php/solr.php --create-server, then restart Solr. Run --help first; flags drifted between releases.
  2. Index — trigger a full reindex from the ezfind/index admin view or the indexing script under extension/ezfind/bin/php/, then commit.

Where to look first, in this order: extension/ezfind/settings/solr.ini.append.php (all the knobs), extension/ezfind/solr/ (the schema.xml / solrconfig.xml you will actually edit), extension/ezfind/classes/ezsolr.php (the eZSolr facade: instance(), search(), addObject(), removeObject(), commit()), and extension/ezfind/modules/ezfind/ (the search / index / solr views).

First use case: replace a content/search fetch in a template with an ezfind fetch and loop the results:

{def $result = fetch( 'ezfind', 'search', hash(
    'query', $q,
    'limit', 10,
    'offset', 0
) )}

<p>{$result.SearchCount} results for "{$q|wash}"</p>
{foreach $result.SearchResult as $node}
    <a href={$node.url_alias|ezurl}>{$node.name|wash}</a>
{/foreach}

Attribute names on the result object vary slightly by release — {$result|attribute(show, 1)} once and you will know exactly what you have.

Implementation Patterns

Search with filters, sorting and facets. Almost all day-to-day work happens in this one fetch. Filters are raw Solr field syntax, so keep them in your own PHP/template helper rather than scattering strings across templates:

{def $result = fetch( 'ezfind', 'search', hash(
    'query', $q,
    'limit', 20,
    'sort_by', hash( 'published', 'desc' ),
    'filter', array( 'class_id:12', 'attr_published:[2015-01-01T00:00:00Z TO NOW]' ),
    'facet', array( '#class_id', '#attr_category' ),
    'subtree_array', array( 2 )
) )}

Prefer subtree_array over hand-built path filters — it is the supported way to scope results under a node, and on 2017.12 it is the only path that correctly accounts for hidden nodes and objects with multiple locations (EZP-23644) and for non-main-node links (EZP-24021). Read facet counts off the result object and build the facet UI as "toggle a filter in the query string, refetch", which keeps the whole thing cacheable and bookmarkable.

Facet field output changed in 2017.12. EZP-27738 makes the facet_fields list return the field name as the field value, so the old assumption that you could read the query-side name off the result no longer holds. If you have template code that reads facet metadata positionally, dump {$result.FacetFields|attribute(show, 1)} once after upgrading and adjust — this one bites silently (facets render with empty labels rather than erroring).

Section filtering. 2017.12 adds proper support for a list of section IDs in the search filter (EZP-26804). If you have been hand-rolling meta_section_id filters with OR, replace them with the supported parameter.

Related content. fetch( 'ezfind', 'more_like_this', hash( 'object_id', $node.contentobject_id, 'limit', 5 ) ) is the cheap win for "you may also like" blocks.

Indexing strategy. Keep [IndexOptions] IndexOnPublish=enabled for normal editorial traffic, but do not rely on it as the source of truth. Add a nightly/off-hours full reindex via cron — publishes that fail mid-request, objects deleted outside the CMS, and direct DB edits all leave the index drifting. For bulk imports or migrations, disable index-on-publish, run the import, then reindex in one pass; per-object Solr commits will otherwise dominate your import wall-clock time.

Programmatic access. Inside a custom module, workflow event, or cron script, skip the template layer:

$solr  = eZSolr::instance();
$query = new eZFindQuery( '...' ); // or build via the fetch-parameter equivalent
$result = $solr->search( $query );

Wrap this in your own thin service class. That wrapper is what you will port to a real search client if the site ever moves off legacy — do not let raw fetch() calls metastasise through 200 templates.

Custom datatype indexing. Custom content classes mostly work out of the box because eZ Find uses Solr dynamic fields keyed off attr_<identifier>; you only subclass ezfSolrDocumentFieldBase (see the ezfSolrDocumentField* classes alongside it) when a datatype needs a genuinely new Solr type or a getSortFieldName() of its own. Note EZP-21831 fixed asObject=false handling for custom fields — if you had a workaround for that in your subclass, revisit it on 2017.12.

Boosting. Relevance tuning lives in the solr.ini boost settings plus per-field weights, not in template code. EZP-24739 fixed IndexBoost being ignored in some locales, so if you previously compensated for locale-dependent boost behaviour in query code, that compensation is now distorting your ranking — remove it. Change boosts in INI, reindex, compare — and write down what you changed, because it is invisible six months later.

Gotchas and Tips

  • Settings that "don't apply" are almost always stale INI or template caches. After every .ini.append.php edit: clear var/<siteaccess>/cache/ini and the template cache. This is the single most common false bug report on this stack.
  • .append.php merge semantics are not deep-merges. Plain keys override; array keys ([]=) append. A siteaccess file and an override file both touching the same array can produce a value you did not expect. Verify the effective config rather than trusting the file you just edited.
  • New classes need autoloads. Adding an extension class without rerunning ezpgenerateautoloads.php gives you a fatal error that looks like a missing file. Same for anything you add under extension/ezfind/classes/. After a version bump this is mandatory, not optional.
  • Upgrading to 2017.12 is a coordinated change. It requires legacy 2017.10+ and PHP 7 (EZP-212 / EZP-21764: parent constructors called correctly, no eZINI instantiation outside classes). Bumping the package without bumping the legacy kernel gives you fatals that look unrelated to search. Pin both together, and reindex fully after the switch — the document-building code path changed.
  • Sorting needs a sort field. Text attributes are indexed with a companion *_sort field; sorting on a non-sort or unknown field returns a Solr error, not an empty result set. When a search mysteriously 500s, curl Solr directly and read its error message — that tells you instantly whether the problem is eZ or Solr.
  • Schema changes require a full cycle: stop/reload the core, reindex everything, then commit. Avoid schema edits by leaning on the dynamic field suffixes (_s, _t, _i, _si, _ms) whenever you can.
  • No commit, no results. Bulk indexing without a final commit makes documents invisible. Check the solrconfig.xml autoCommit settings before assuming your indexer is broken.
  • Deletes and renames leave orphans. If content disappears from eZ Publish through any path other than the normal object lifecycle, the Solr document survives and shows up as a dead link. The periodic full reindex is your garbage collector.
  • Multicore + multilanguage has a known-fixed quirk. EZP-23878 (no result when exactly one location exists across several languages) is fixed in 2017.12. If you are on an older release and see "it works for two translations but not one", that is your bug — do not go hunting in your query code.
  • Exact-phrase searches and camelCase. EZP-24553 fixed zero-result exact-phrase matching for camelCase words. Worth retesting your phrase-search test suite after upgrading; results will differ from 2015.01 for those queries.
  • Do not assume ACL enforcement. The index is a flat document store; results are turned back into nodes for display. If your site has meaningful read restrictions, post-filter with the node's can_read (or equivalent access check) rather than trusting the query.
  • Solr version drift is a trap. The shipped schema and solrconfig.xml are written for Solr 4.x. Newer Solr servers will reject them. Pin the Solr version in your infrastructure config and treat any upgrade as a migration project, not a patch.
  • Debug by bisecting. Log the generated Solr query, then replay it with curl 'http://localhost:8983/solr/<core>/select?q=...&wt=json'. That one habit separates "our query is wrong" from "the core is down" in seconds.
  • This package is maintenance-only, and 2017.12 is a compatibility release — not a revival. It ships no new features and no security posture; it exists so a PHP 7 legacy install keeps working. It remains bound to the eZ Publish legacy stack, which is itself end-of-life. Use it to maintain an existing install, isolate it behind your own search wrapper, and plan the exit rather than building new features directly against fetch( 'ezfind', ... ).
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.
pharaonic/laravel-notification-dependencies
beautinow/translug
dev-brainiac/bot-cloaked
octoberrain/html
octoberrain/extension
octoberrain/exception
octoberrain/contracts
frankyso/ipaymu
3mdikram/worldmoneywords
snowsoft/config
itmosoft/laravel-subscriptions
larva/laravel-ai-qwen
adachsoft/api-version-bundle
cgv/localized-resource
noith/settings
kda/laravel-package
kda/filament-dynamic-navigation
bypersoft/signbox
pairus/product-data
fayne/laravel-filament-cms-core