Weave Code
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 Bundle Laravel Package

massive/search-bundle

Laravel bundle that adds a flexible, driver-based search layer to your app. Define searchable models and fields, run queries across multiple sources, and return consistent results with pagination and filtering—designed to be easy to integrate and extend.

View on GitHub
Deep Wiki
Context7

Getting Started

Minimal Setup

  1. Installation:

    composer require massive/search-bundle
    

    Add to config/bundles.php (Symfony) or configure via Laravel's service provider equivalent (if using a bridge like symfony/bridge).

  2. Configure Backend: Edit config/packages/massive_search.yaml (Symfony) or equivalent Laravel config:

    massive_search:
        clients:
            default:
                type: elasticsearch
                host: 'http://localhost:9200'
                index_name: 'app_%kernel.environment%'
        adapters:
            default: ~
    
  3. First Use Case: Annotate an entity to enable search:

    use Massive\SearchBundle\Annotation as Search;
    
    /**
     * @Search\Index(name="product", type="product")
     */
    class Product {}
    

    Reindex via CLI:

    php artisan massive:search:reindex Product
    
  4. Basic Query:

    $searchManager = $container->get('massive_search.search_manager');
    $results = $searchManager->search('product', [
        'query' => 'title:php',
        'page' => 1,
        'limit' => 10
    ]);
    

Implementation Patterns

Core Workflows

  1. Entity Indexing:

    • Use @Search\Index annotations or YAML/XML mappings for automatic indexing.
    • Partial reindexing:
      php artisan massive:search:reindex Product --locale=en
      
  2. Query Construction:

    • Expression Language for dynamic filters:
      $query = $searchManager->createQueryBuilder('product')
          ->where('title = :title', ['title' => 'Laravel'])
          ->andWhere('price > 10')
          ->getQuery();
      
    • Block-Based Queries (for complex logic):
      $query = [
          'bool' => [
              'must' => [
                  ['match' => ['title' => 'Laravel']],
                  ['range' => ['price' => ['gt' => 10]]]
              ]
          ]
      ];
      
  3. Pagination & Sorting:

    $results = $searchManager->search('product', [
        'query' => $query,
        'sort' => ['created_at' => 'desc'],
        'page' => 2,
        'limit' => 20
    ]);
    
  4. Event-Driven Extensions: Subscribe to SearchEvent to modify queries or results:

    $eventDispatcher->addListener(SearchEvent::PRE_SEARCH, function (SearchEvent $event) {
        $event->getQuery()->addBoost('title', 2.0);
    });
    

Integration Tips

  • Laravel-Specific: Use MassiveSearchServiceProvider to bridge Symfony components:

    $this->app->bind('massive_search.search_manager', function ($app) {
        return new \Massive\SearchBundle\Search\SearchManager(
            $app['massive_search.client.default'],
            $app['massive_search.adapter.default']
        );
    });
    
  • Custom Field Mappings: Override default mappings via massive_search.yaml:

    massive_search:
        mappings:
            Product:
                fields:
                    title:
                        type: text
                        analyzer: custom_analyzer
    
  • Multi-Backend Queries:

    $multiSearcher = $container->get('massive_search.multi_searcher');
    $results = $multiSearcher->search([
        'product' => ['query' => 'title:php'],
        'article' => ['query' => 'content:laravel']
    ]);
    

Gotchas and Tips

Pitfalls

  1. PHP/Doctrine Version Mismatch:

    • Drop support for PHP ≤8.1 and Symfony ≤5.3 in v2.10.0. Ensure compatibility:
      composer require symfony/*:^6.4|^7.0 php:^8.2
      
  2. Serialization Loops:

    • PHP 8.3+ may trigger serialization errors with IndexMetadata. Use:
      // In a custom event subscriber
      $event->getQuery()->setOption('serialize_metadata', false);
      
  3. Locale-Specific Indexing:

    • Deindexing a single locale requires explicit locale specification:
      php artisan massive:search:deindex Product --locale=fr
      
  4. Zend Lucene Quirks:

    • Sorting in multi-index searches may fail. Use optimize command:
      php artisan massive:search:optimize
      

Debugging Tips

  • Query Validation: Enable debug mode in massive_search.yaml:

    massive_search:
        debug: true
    

    Logs raw queries to var/log/massive_search.log.

  • Field Evaluator Issues: Null checks in FieldEvaluator::getPropertyValue (fixed in v2.9.5) may cause silent failures. Verify with:

    $evaluator = $container->get('massive_search.field_evaluator');
    $value = $evaluator->getPropertyValue($entity, 'non_existent_field'); // Returns null
    
  • Expression Language Errors: Use value() function for existence checks:

    $query->where('value(attributes.tags) IS NOT NULL');
    

Extension Points

  1. Custom Backends: Implement Massive\SearchBundle\Search\Adapter\AdapterInterface for new search engines (e.g., Meilisearch).

  2. Query Modifiers: Extend Massive\SearchBundle\Search\Query\QueryBuilder to add custom clauses:

    class CustomQueryBuilder extends QueryBuilder {
        public function customBoost($field, $factor) {
            $this->query['boost'] = [$field => $factor];
            return $this;
        }
    }
    
  3. Indexing Strategies: Override Massive\SearchBundle\Indexer\IndexerInterface for custom indexing logic (e.g., async indexing).

  4. Event Subscribers: Modify search behavior via SearchEvent:

    $eventDispatcher->addListener(SearchEvent::POST_SEARCH, function (SearchEvent $event) {
        $event->getResults()->setTotalHits($event->getResults()->getTotalHits() * 2);
    });
    

Performance Quirks

  • Elasticsearch 8 Compatibility: Use compatibility mode in massive_search.yaml:

    clients:
        default:
            type: elasticsearch
            compatibility_mode: 7
    
  • Subfield Indexing: Enable via annotation:

    /**
     * @Search\Index(name="product", type="product")
     * @Search\Field(name="tags", type="text", subfields=true)
     */
    class Product {}
    
  • Memory Leaks: Avoid serializing large entities. Use hydrate=false in queries:

    $results = $searchManager->search('product', [
        'query' => $query,
        'hydrate' => false
    ]);
    
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.
milito/query-filter
apiboxsym/user-bundle
apiboxsym/health-check-bundle
jayeshmepani/jpl-moshier-ephemeris-php
elnasnato/laraliveui
labrodev/rest-sdk
sampaui/sampaui
babelqueue/php-sdk
facebook/capi-param-builder-php
babelqueue/symfony
hamzi/corewatch
minionfactory/raw-hydrator
hexters/coinpayment
rjcodes/rjcms
act-training/laravel-permissions-manager
alimarchal/laravel-chart-of-accounts
babenkoivan/elastic-scout-driver
mkwebdesign/filament-watchdog-v5
renatomarinho/laravel-page-speed
zedmagdy/filament-business-hours