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

Rigid Search Bundle Laravel Package

demontpx/rigid-search-bundle

View on GitHub
Deep Wiki
Context7

Getting Started

Minimal Steps

  1. Installation

    composer require demontpx/rigid-search-bundle
    

    Ensure DemonTPx\RigidSearchBundle\DemonTPxRigidSearchBundle::class is registered in config/bundles.php (Symfony) or config/app.php (Laravel via bridge).

  2. Define a Searchable Entity Create a SearchDocumentExtractor class implementing SearchDocumentExtractorInterface for your entity (e.g., NewsItem). Example:

    use DemonTPx\RigidSearchBundle\Document\Document;
    use DemonTPx\RigidSearchBundle\Document\SearchDocumentExtractorInterface;
    
    class NewsItemDocumentExtractor implements SearchDocumentExtractorInterface {
        public function extractDocument($item): Document {
            $document = new Document(
                $item->getTitle(),
                $item->getDescription(),
                $item->getPublishDate(),
                route('news.show', $item)
            );
    
            $document->addField('title', $item->getTitle(), 10);
            $document->addField('content', $item->getContent(), 5);
            $document->addField('tags', implode(',', $item->getTags()), 3);
    
            return $document;
        }
    }
    
  3. Register the Extractor Bind the extractor to your entity in the bundle’s configuration (config/packages/demontpx_rigid_search.yaml):

    rigid_search:
        extractors:
            App\Entity\NewsItem: App\DocumentExtractor\NewsItemDocumentExtractor
    
  4. Index Entities Use the RigidSearchManager to index entities:

    $manager = $this->container->get('rigid_search.manager');
    $manager->indexEntity(new NewsItem());
    
  5. Search Entities

    $results = $manager->search('query', NewsItem::class);
    

Implementation Patterns

Workflows

  1. Incremental Indexing Index entities in batches (e.g., during cron jobs) to avoid performance spikes:

    $batch = $entityManager->getRepository(NewsItem::class)->findBy([], [], 100);
    foreach ($batch as $item) {
        $manager->indexEntity($item);
    }
    
  2. Real-Time Updates Trigger indexing after entity creation/updates via Doctrine lifecycle callbacks:

    use Doctrine\ORM\Event\LifecycleEventArgs;
    
    class NewsItem {
        // ...
        public function postPersist(LifecycleEventArgs $args) {
            $manager = $args->getEntityManager()->getService('rigid_search.manager');
            $manager->indexEntity($this);
        }
    }
    
  3. Hybrid Search Combine with Laravel Scout or Algolia for multi-layered search:

    // Fallback to rigid-search if Scout fails
    try {
        $results = $entity->search('query');
    } catch (\Exception $e) {
        $results = $manager->search('query', $entity::class);
    }
    

Integration Tips

  • Custom Relevance Logic Override Document::addField() weights dynamically (e.g., boost recent items):

    $weight = $item->getPublishDate()->diff(new \DateTime())->days < 7 ? 15 : 5;
    $document->addField('title', $item->getTitle(), $weight);
    
  • Multi-Entity Search Search across multiple entity types by chaining results:

    $newsResults = $manager->search('query', NewsItem::class);
    $articleResults = $manager->search('query', Article::class);
    $results = array_merge($newsResults, $articleResults);
    
  • Pagination Use Document::setPageSize() and setPage() for client-side pagination:

    $manager->search('query', NewsItem::class, 1, 10); // Page 1, 10 items
    

Gotchas and Tips

Pitfalls

  1. Field Weighting

    • Weights are relative, not absolute. A weight of 10 vs. 5 means the first field is twice as important, not "10x better."
    • Fix: Normalize weights (e.g., max weight = 100) for consistency.
  2. Case Sensitivity

    • Searches are case-sensitive by default. Use strtolower() in extractDocument() for case-insensitive searches:
      $document->addField('title', strtolower($item->getTitle()), 10);
      
  3. Memory Limits

    • Large datasets may hit PHP memory limits during indexing.
    • Fix: Process in smaller chunks or use a queue (e.g., Laravel Queues).
  4. URL Generation

    • Hardcoded URLs in Document break in multi-environment setups.
    • Fix: Use Laravel’s route() or Symfony’s UrlGeneratorInterface:
      $this->generateUrl($item) => route('news.show', $item);
      
  5. No Built-in Full-Text Search

Debugging

  • Verify Indexed Data Dump the extracted document to debug field weights and content:

    $extractor = new NewsItemDocumentExtractor();
    $document = $extractor->extractDocument($newsItem);
    dd($document->getFields());
    
  • Check Search Queries Log raw search queries to validate input:

    $manager->search('query', NewsItem::class, 1, 10, true); // Enable debug mode
    

Extension Points

  1. Custom Scoring Extend Document to add custom scoring logic:

    class CustomDocument extends Document {
        public function calculateRelevance($query) {
            $baseScore = parent::calculateRelevance($query);
            // Add custom logic (e.g., boost for featured items)
            return $baseScore * ($this->isFeatured() ? 1.5 : 1);
        }
    }
    
  2. Plugin System Create a SearchPluginInterface to add pre/post-processing:

    interface SearchPluginInterface {
        public function preSearch(array &$options);
        public function postSearch(array &$results);
    }
    
  3. Laravel Bridge For Laravel, publish the config and create a service provider to bind the manager:

    // config/services.php
    'rigid_search.manager' => \DemonTPx\RigidSearchBundle\Manager\RigidSearchManager::class,
    
    // app/Providers/AppServiceProvider.php
    public function register() {
        $this->app->bind('rigid_search.manager', function ($app) {
            return new \DemonTPx\RigidSearchBundle\Manager\RigidSearchManager(
                $app['rigid_search.extractor_registry'],
                $app['config']['rigid_search']
            );
        });
    }
    
  4. Caching Cache search results for high-traffic queries:

    $cacheKey = 'search:news:' . md5('query' . NewsItem::class);
    $results = Cache::remember($cacheKey, 3600, function () use ($manager) {
        return $manager->search('query', NewsItem::class);
    });
    
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.
terminal42/code-quality-tools
codifyo/ts-generator-bundle
testo/fiber
mintobit/jobqueue
a4sex/maintenance-bundle
a4sex/entity-date-update
a4sex/client-identifier
a4sex/base-utilites
a4sex/key-value-storage
a4sex/micro-status
chilldev/dependency-injection-extra
datinglibre/datinglibre-app-api
biberltd/corebundle
bricre/symfony-bundle-test
biberltd/logbundle
dominium/http-adapter-bundle
dominium/google-analytics
a4sex/auto-clean-entity
christhompsontldr/laravel-inky
spatie/mailcoach-vapor