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

araise/search-bundle

View on GitHub
Deep Wiki
Context7

Getting Started

Minimal Setup

  1. Install the package:

    composer require araise/search-bundle
    
  2. Enable MySQL MATCH AGAINST in Doctrine: Add to config/packages/doctrine.yaml:

    doctrine:
        orm:
            dql:
                string_functions:
                    MATCH_AGAINST: araise\SearchBundle\Extension\Doctrine\Query\Mysql\MatchAgainst
    
  3. Update schema:

    php bin/console doctrine:schema:update --force
    
  4. Annotate fields in your entity:

    use araise\SearchBundle\Annotation\Index;
    
    #[ORM\Entity]
    class Post {
        #[Index] // Marks this field for full-text search
        private string $title;
    }
    
  5. Populate the index:

    php bin/console araise:search:populate
    

First Use Case

Search for posts in a controller:

use araise\SearchBundle\Repository\IndexRepository;

#[Route('/search', name: 'search_posts')]
public function search(IndexRepository $indexRepo, Request $request) {
    $query = $request->query->get('q');
    $postIds = $indexRepo->search($query, Post::class);
    // Fetch full entities via PostRepository
}

Implementation Patterns

1. Indexing Workflow

  • Annotate fields: Use @Index on Doctrine entity properties.
  • Populate index: Run araise:search:populate (cron-friendly for large datasets).
  • Custom queries: Implement CustomSearchPopulateQueryBuilderInterface for filtered indexing.

2. Search Patterns

  • Entity-specific search:
    $ids = $indexRepo->search('query', Post::class);
    
  • Multi-entity search:
    $results = $indexRepo->searchEntities('query');
    // Map results to objects manually
    
  • Search options (e.g., groups):
    $options = new SearchOptions(['groups' => ['posts']]);
    $ids = $indexRepo->search($query, Post::class, $options);
    

3. Integration with Symfony Forms

  • Bind search input to a form field and pass the query to the controller.

4. Pagination

  • Use Doctrine’s setMaxResults()/setFirstResult() on the fetched entities after retrieving IDs.

5. Real-Time Updates

  • Trigger araise:search:populate after entity CRUD operations (e.g., via event listeners).

Gotchas and Tips

Pitfalls

  1. MySQL Dependency:

    • MATCH AGAINST requires MySQL. Test on your target DB early.
    • Fix: Use a compatible DB or mock the function in tests.
  2. Index Population:

    • Initial population can be slow for large datasets. Test with --limit:
      php bin/console araise:search:populate --limit=1000
      
    • Tip: Schedule via cron with --chunk-size for incremental updates.
  3. Case Sensitivity:

    • MySQL’s MATCH AGAINST is case-insensitive by default. Use BOOLEAN MODE for control:
      // In a custom QueryBuilder hook
      $qb->andWhere("MATCH_AGAINST($alias.title, :query) > 0")
        ->setParameter('query', $query . ' WITH QUERY EXPANSION');
      
  4. Wildcards:

    • Disable asterisk_search_enabled in araise_search.yaml if you don’t need * wildcards (improves performance).
  5. Field Formatting:

    • Custom formatters (e.g., for dates) must implement araise\CoreBundle\Formatter\FormatterInterface.
    • Tip: Cache formatted values if performance is critical.

Debugging Tips

  • Check index status:
    php bin/console araise:search:status
    
  • Log queries: Enable Doctrine logging to inspect MATCH AGAINST queries.
  • Test hooks: Use preSearch/postSearch hooks to debug query results:
    // In UserPreSearch::preSearch()
    $qb->andWhere("MATCH_AGAINST($alias.title, :query) > 5"); // Boost relevance
    

Extension Points

  1. Custom Scoring:

    • Override postSearch to filter/rank results:
      public function postSearch(array $results, string $query): array {
          return array_filter($results, fn($r) => $r['_matchQuote'] > 10);
      }
      
  2. Dynamic Indexing:

    • Implement araise\SearchBundle\Event\SearchPopulateEventListener to skip entities conditionally.
  3. Alternative Backends:

    • Replace MatchAgainst with a custom DQL function for non-MySQL databases (requires extending the bundle).

Performance Quirks

  • Index Groups: Use groups to limit indexed fields (reduces storage/processing).
  • Field Selection: Avoid indexing large text fields unless necessary.
  • Caching: Cache search results if queries are repeated (e.g., autocomplete).

Configuration Gotchas

  • asterisk_search_enabled: Set to true only if you need wildcard searches (e.g., *term).
  • Formatter Classes: Must be autoloadable and implement the correct interface.
  • Entity Changes: Re-run araise:search:populate after adding/removing @Index fields.
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.
comsave/common
alecsammon/php-raml-parser
chrome-php/wrench
lendable/composer-license-checker
typhoon/reflection
mesilov/moneyphp-percentage
mike42/gfx-php
bookdown/themes
aura/view
aura/html
aura/cli
povils/phpmnd
nayjest/manipulator
omnipay/tests
psr-mock/http-message-implementation
psr-mock/http-factory-implementation
psr-mock/http-client-implementation
voku/email-check
voku/urlify
rtheunissen/guzzle-log-middleware