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

chub/search-bundle

View on GitHub
Deep Wiki
Context7

Getting Started

Minimal Setup

  1. Installation:

    composer require chub/search-bundle
    

    (Note: The README mentions Git installation, but Composer is preferred for modern Symfony.)

  2. Register the Bundle: Add to config/bundles.php (Symfony 4+):

    return [
        // ...
        ChubProduction\SearchBundle\SearchBundle::class => ['all' => true],
    ];
    
  3. First Use Case: Create a simple SearchProvider for a model (e.g., Post):

    use ChubProduction\SearchBundle\Provider\SearchProviderInterface;
    
    class PostSearchProvider implements SearchProviderInterface
    {
        public function getSearchableFields()
        {
            return ['title', 'content']; // Fields to search in
        }
    
        public function search($query, $page = 1, $perPage = 10)
        {
            // Implement logic to fetch posts matching $query
            // Return a paginated result (e.g., Doctrine Paginator)
        }
    }
    
  4. Service Configuration: Register the provider in config/services.yaml:

    services:
        App\Search\PostSearchProvider:
            tags: ['search.provider']
    
  5. Trigger a Search: Inject the SearchService (auto-registered) and call:

    $results = $searchService->search('query', 'post'); // 'post' is the provider key
    

Implementation Patterns

Core Workflow

  1. Provider-Based Architecture:

    • Each entity (e.g., Post, User) has a dedicated SearchProvider.
    • Providers implement SearchProviderInterface with:
      • getSearchableFields(): Define which fields to index/search.
      • search($query, $page, $perPage): Return paginated results.
  2. Integration with Controllers:

    use ChubProduction\SearchBundle\Search\SearchService;
    
    class SearchController extends AbstractController
    {
        public function index(SearchService $search, Request $request)
        {
            $query = $request->query->get('q');
            $results = $search->search($query, 'post'); // 'post' = provider key
            return $this->render('search/index.html.twig', ['results' => $results]);
        }
    }
    
  3. Twig Integration: Pass results to Twig and loop:

    {% for result in results %}
        <h2>{{ result.title }}</h2>
        <p>{{ result.content|truncate(100) }}</p>
    {% endfor %}
    
  4. Pagination: The bundle expects providers to return objects supporting getCurrentPage(), setCurrentPage(), etc. (e.g., KnpPaginator, Doctrine Paginator).


Advanced Patterns

  1. Dynamic Provider Loading: Use the SearchService to dynamically load providers by key:

    $searchService->addProvider('dynamic_key', new DynamicSearchProvider());
    
  2. Combining Results: Merge results from multiple providers:

    $posts = $searchService->search('query', 'post');
    $users = $searchService->search('query', 'user');
    $combined = array_merge($posts->getResults(), $users->getResults());
    
  3. Custom Search Logic: Extend SearchService or override provider methods for complex queries (e.g., full-text search with Solr/Elasticsearch).

  4. Caching: Cache search results in the provider’s search() method:

    $cacheKey = md5($query . $page);
    return $cache->get($cacheKey, function() use ($query, $page) {
        return $this->fetchFromDatabase($query, $page);
    });
    

Gotchas and Tips

Common Pitfalls

  1. Provider Key Mismatch:

    • Ensure the key passed to search() (e.g., 'post') matches the service ID in services.yaml.
    • Debug: Check SearchService::getProviders() to list registered keys.
  2. Pagination Issues:

    • Providers must return objects with pagination methods (e.g., getResults(), getTotalItems()).
    • Use KnpPaginator or Doctrine Paginator for consistency:
      $paginator = $this->getDoctrine()
          ->getManager()
          ->getRepository(Post::class)
          ->createQueryBuilder('p')
          ->where('p.title LIKE :query')
          ->setParameter('query', "%$query%")
          ->getQuery()
          ->getResult();
      $paginator = new Paginator($paginator, $fetchJoinCollection = true);
      
  3. Field Matching:

    • getSearchableFields() returns an array of field names, not database columns. Ensure these match your entity properties or query logic.
  4. Case Sensitivity:

    • The bundle does not handle case sensitivity by default. Add LOWER() or ILIKE in your provider’s query:
      ->where('LOWER(p.title) LIKE LOWER(:query)')
      

Debugging Tips

  1. Log Provider Calls: Override SearchService to log queries:

    public function search($query, $providerKey)
    {
        $this->logger->debug(sprintf('Searching "%s" in provider "%s"', $query, $providerKey));
        return parent::search($query, $providerKey);
    }
    
  2. Validate Results: Check if results are empty due to:

    • Incorrect getSearchableFields().
    • Query syntax errors in the provider.
    • Database connection issues.
  3. Performance:

    • Avoid wildcards (%query%) in large tables. Use prefix searches (query%) or full-text indexes.
    • Profile slow providers with EXPLAIN (Doctrine) or Xdebug.

Extension Points

  1. Custom Search Service: Extend SearchService to add features like:

    • Query parsing (e.g., title:query for field-specific searches).
    • Result ranking/sorting.
  2. Event Listeners: Attach listeners to search.before/search.after events (if the bundle supports them; check source for events).

  3. Alternative Data Sources: Replace the default provider logic to integrate with:

    • Elasticsearch (use Elasticsearch\Client in the provider).
    • Algolia or Meilisearch (similar approach).
  4. Configuration: Override bundle parameters in config/packages/chub_search.yaml (if supported). Example:

    chub_search:
        default_provider: 'post' # Set a default provider key
        timeout: 5               # Search timeout (seconds)
    

Pro Tips

  1. Use DTOs for Results: Transform raw entities into Data Transfer Objects (DTOs) in the provider to decouple search logic from your domain model.

  2. Highlight Matches: Modify the provider to return highlighted snippets:

    public function search($query, $page = 1, $perPage = 10)
    {
        $results = $this->fetchFromDatabase($query, $page, $perPage);
        foreach ($results as $result) {
            $result->setHighlightedContent($this->highlightMatches($result->content, $query));
        }
        return $results;
    }
    
  3. Autocomplete: Add a suggest() method to providers for type-ahead:

    public function suggest($query, $limit = 5)
    {
        return $this->getEntityManager()
            ->createQueryBuilder()
            ->select('p.title')
            ->from(Post::class, 'p')
            ->where('p.title LIKE :query')
            ->setParameter('query', "$query%")
            ->setMaxResults($limit)
            ->getQuery()
            ->getResult();
    }
    
  4. Symfony Messenger: For async search (e.g., indexing), dispatch a SearchQueryMessage via Messenger and process it in a worker.

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.
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
renatovdemoura/blade-elements-ui
devgeek/beacon-admin
benjamin-rqt/data-watcher-bundle