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

Matcher Laravel Package

loupe/matcher

PHP library for search term highlighting and contextual snippet generation. Tokenize queries (phrases, negation, locale-aware rules), match terms with stop-word filtering and span positions, then format results with highlights and cropped excerpts for user-friendly search output.

View on GitHub
Deep Wiki
Context7

Technical Evaluation

Architecture Fit

  • Search UX Enhancement: Ideal for Laravel applications requiring search result snippets with highlighted terms (e.g., internal wikis, e-commerce product search, or documentation systems). The three-tiered architecture (TokenizerMatcherFormatter) maps cleanly to Laravel’s service-oriented design, enabling reusable components.
  • Text Processing Pipeline: Supports locale-aware tokenization (via ext-intl) and advanced query syntax (phrases, negations), making it suitable for multilingual or complex search use cases. The pre-calculated matches feature aligns with Laravel’s caching mechanisms (e.g., Illuminate\Support\Facades\Cache).
  • Extensibility: Custom tokenizers and formatters allow integration with existing search backends (e.g., Laravel Scout, Elasticsearch, or database-driven full-text search). The Cropper class enables standalone cropping of pre-highlighted text, useful for edge cases.
  • Frontend Agnostic: Configurable HTML tags (<mark>, <em>, etc.) ensure compatibility with Blade templates, Livewire, or Inertia.js for dynamic rendering.

Technical Risk

  • API Instability: The "work in progress" warning in the README indicates potential breaking changes before 1.0. Mitigation: Pin to a specific version (e.g., ^0.2.4) and monitor GitHub milestones for stabilization.
  • Performance Overhead: Tokenization and matching may introduce latency for high-volume searches. Mitigation:
    • Cache matches using Laravel’s cache system.
    • Pre-calculate matches for frequent queries (e.g., trending search terms).
  • Dependency on ext-intl: Locale-aware tokenization requires the PHP intl extension. Mitigation: Document this requirement in composer.json and test environments.
  • No Built-in Full-Text Search: Relies on external search engines (e.g., Scout, Algolia) for indexing. Mitigation: Design the pipeline to accept pre-tokenized queries/matches from these services.

Key Questions

  1. Search Backend Compatibility:
    • How will this integrate with our existing search backend (e.g., Scout, Elasticsearch, or database queries)?
    • Can we leverage pre-calculated matches from the backend to avoid redundant tokenization?
  2. Performance Benchmarks:
    • What are the expected latency impacts for our average search result set size (e.g., 100 vs. 10,000 results)?
    • Should we implement a fallback to simpler highlighting (e.g., regex-based) for performance-critical paths?
  3. Frontend Integration:
    • How will highlighted snippets be rendered in Blade/Livewire/Inertia? Will we need custom CSS for the highlight tags?
    • Should we support Markdown or other markup formats alongside HTML?
  4. Localization:
    • Do we need multilingual support, or is English sufficient for our use case?
    • How will we handle right-to-left (RTL) languages or non-Latin scripts?
  5. Testing and Stability:
    • What’s the plan for regression testing as the API evolves toward 1.0?
    • Should we contribute to the project (e.g., tests, docs) to influence its direction?

Integration Approach

Stack Fit

  • Laravel Ecosystem:
    • Service Container: Register the Tokenizer, Matcher, and Formatter as Laravel services for dependency injection.
    • Facade: Create a MatcherFacade to simplify usage (e.g., Matcher::highlight($text, $query)).
    • Service Providers: Bundle configuration (e.g., default stop words, crop lengths) in a LoupeMatcherServiceProvider.
  • Query Builder Integration:
    • Extend Laravel’s query builder to include snippet generation for LIKE or full-text search results (e.g., Post::search($query)->withSnippets()).
    • Use database views or application logic to fetch raw text and apply highlighting.
  • Caching Layer:
    • Cache matches and formatted snippets using Laravel’s cache system (e.g., Cache::remember()) to avoid reprocessing identical queries.
    • Example:
      $snippet = Cache::remember("snippet:{$query}:{$documentId}", now()->addHours(1), function() use ($query, $document) {
          return $formatter->format($document->body, $query, $options);
      });
      

Migration Path

  1. Phase 1: Proof of Concept (1 Sprint)
    • Integrate the package in a non-critical feature (e.g., admin search or documentation preview).
    • Test with a small dataset (e.g., 100–1000 documents) to validate performance and accuracy.
    • Document edge cases (e.g., special characters, multiline text).
  2. Phase 2: Core Integration (2 Sprints)
    • Register services in Laravel’s container and create a facade.
    • Integrate with the primary search backend (e.g., Scout or Elasticsearch) to fetch raw text and apply highlighting.
    • Implement caching for frequent queries.
  3. Phase 3: Optimization (1 Sprint)
    • Benchmark performance and optimize for large datasets (e.g., batch processing, parallel tokenization).
    • Add monitoring for snippet generation latency.
  4. Phase 4: Frontend Sync (1 Sprint)
    • Ensure highlighted snippets render correctly in Blade/Livewire/Inertia.
    • Add CSS classes for highlight tags (e.g., .highlight for styling).

Compatibility

  • Laravel Versions: Tested with Laravel 10+ (PHP 8.1+). Ensure ext-intl is enabled (php -m | grep intl).
  • Dependencies:
    • No conflicts with Laravel core or popular packages (e.g., Scout, Livewire).
    • Optional: symfony/options-resolver (already a Laravel dependency).
  • Database Agnostic: Works with any text stored in the database (e.g., Post::body, Product::description).

Sequencing

  1. Prerequisites:
    • Enable ext-intl in php.ini and verify with php -m.
    • Install the package: composer require loupe/matcher.
  2. Core Setup:
    • Register services in AppServiceProvider:
      public function register()
      {
          $this->app->bind(Tokenizer::class, fn() => new Tokenizer('en_US'));
          $this->app->bind(Matcher::class, fn($app) => new Matcher($app->make(Tokenizer::class)));
          $this->app->bind(Formatter::class, fn($app) => new Formatter($app->make(Matcher::class)));
      }
      
  3. Facade (Optional):
    • Create app/Facades/Matcher.php:
      public static function highlight(string $text, string $query, ?FormatterOptions $options = null): string
      {
          return app(Formatter::class)->format($text, $query, $options)->getFormattedText();
      }
      
  4. Usage Example:
    use App\Facades\Matcher;
    
    $snippet = Matcher::highlight(
        $product->description,
        'wireless earbuds',
        (new FormatterOptions())
            ->withCropLength(150)
            ->withHighlightStartTag('<strong>')
    );
    

Operational Impact

Maintenance

  • Dependency Updates:
    • Monitor loupe/matcher for breaking changes (watch GitHub releases).
    • Update in lockstep with Laravel/PHP versions (e.g., test against PHP 8.2+).
  • Configuration Drift:
    • Centralize formatter options (e.g., crop lengths, highlight tags) in a config file (config/loupe-matcher.php).
    • Example:
      'default_options' => [
          'crop_length' => 150,
          'highlight_start_tag' => '<mark>',
          'highlight_end_tag' => '</mark>',
      ],
      
  • Deprecation Plan:
    • If the package reaches 1.0, assess whether to fork for long-term stability or continue relying on upstream.

Support

  • Debugging:
    • Log tokenization/matching results for troubleshooting (e.g., Logger::debug($tokens->all())).
    • Create a support script to reproduce issues with sample text/queries.
  • Community:
    • Engage with the GitHub repo (issues, discussions) for edge cases.
    • Contribute tests or documentation if the project lacks coverage for your use case.
  • Fallback Mechanism:
    • Implement a regex-based fallback for critical paths:
      if ($useFallback) {
          return preg_replace(
              "/($query)/i",
              '<mark>$0</mark>',
              $text
          );
      }
      

Scaling

  • Horizontal Scaling:
    • Snippet generation is CPU-bound (tokenization/matching). Offload to a queue (e.g., Laravel Queues) for high-traffic searches.
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
andydefer/laravel-cluster
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