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

becklyn/search-bundle

View on GitHub
Deep Wiki
Context7

Getting Started

Minimal Setup

  1. Installation:

    composer require becklyn/search-bundle
    

    Add to config/bundles.php:

    Becklyn\SearchBundle\BecklynSearchBundle::class => ['all' => true],
    
  2. Configure Elasticsearch: Add to config/packages/becklyn_search.yaml:

    becklyn_search:
        client:
            host: 'http://localhost:9200'
            index_prefix: 'app_'
    
  3. Annotate an Entity:

    use Becklyn\SearchBundle\Entity\SearchableEntityInterface;
    use Becklyn\SearchBundle\Mapping as Search;
    
    /**
     * @Search\Item()
     */
    class Product implements SearchableEntityInterface
    {
        // ...
    }
    
  4. First Indexing:

    php bin/console becklyn:search:index Product
    

First Use Case

Search for products in a controller:

use Becklyn\SearchBundle\Search\SearchInterface;

class ProductController
{
    public function search(SearchInterface $search)
    {
        $results = $search->search('Product', 'query');
        return $this->render('product/search.html.twig', ['results' => $results]);
    }
}

Implementation Patterns

Workflows

  1. Indexing:

    • Manual: Use CLI command (becklyn:search:index EntityName).
    • Automatic: Trigger via event listeners (e.g., prePersist, preUpdate):
      use Becklyn\SearchBundle\Event\IndexEntityEvent;
      use Symfony\Component\EventDispatcher\EventSubscriberInterface;
      
      class IndexSubscriber implements EventSubscriberInterface
      {
          public static function getSubscribedEvents()
          {
              return [
                  IndexEntityEvent::INDEX => 'indexEntity',
              ];
          }
      
          public function indexEntity(IndexEntityEvent $event)
          {
              $event->getIndexer()->index($event->getEntity());
          }
      }
      
  2. Searching:

    • Basic Query:
      $results = $search->search('Product', 'query');
      
    • Advanced Query (using DSL):
      $query = [
          'query' => [
              'bool' => [
                  'must' => [
                      ['match' => ['name' => 'query']],
                      ['range' => ['price' => ['gte' => 10]]],
                  ],
              ],
          ],
      ];
      $results = $search->search('Product', $query);
      
  3. Pagination:

    $results = $search->search('Product', 'query', 1, 10); // page, per_page
    

Integration Tips

  • Doctrine Events: Hook indexing into Doctrine lifecycle events for real-time updates.
  • Symfony Forms: Use SearchType for search form integration:
    use Becklyn\SearchBundle\Form\Type\SearchType;
    
    $builder->add('search', SearchType::class, [
        'entity' => 'Product',
        'property' => 'name',
    ]);
    
  • APIs: Expose search via API Platform or custom controllers:
    #[ApiResource]
    class ProductSearchController
    {
        #[GET('/search', name: 'search_products')]
        public function search(SearchInterface $search, string $query): JsonResponse
        {
            return new JsonResponse($search->search('Product', $query));
        }
    }
    

Gotchas and Tips

Pitfalls

  1. Index Naming Conflicts:

    • Custom index names in @Search\Item() must be unique. Defaults to app_entity_name.
    • Fix: Use index_prefix in config to avoid collisions.
  2. Loader Services:

    • If using a custom loader, ensure the service is properly tagged (becklyn.search.loader).
    • Debug: Check var/log/dev.log for missing service errors.
  3. Localization:

    • For LocalizedSearchableEntityInterface, ensure getLanguage() returns a valid LanguageInterface object.
    • Tip: Use becklyn/interfaces package for consistency.
  4. Mapping Updates:

    • Changes to entity properties require reindexing. Use:
      php bin/console becklyn:search:reindex Product
      
  5. Elasticsearch Connection:

    • If Elasticsearch is down, the bundle throws ConnectionException. Handle gracefully:
      try {
          $results = $search->search('Product', 'query');
      } catch (\Exception $e) {
          // Fallback to database or notify admin
      }
      

Debugging

  • Logs: Enable debug mode (APP_DEBUG=true) for detailed logs in var/log/dev.log.
  • Index Status:
    php bin/console becklyn:search:status
    
  • Query DSL Validation: Use the Elasticsearch Query DSL Analyzer to validate complex queries.

Extension Points

  1. Custom Mappers:

    • Extend Becklyn\SearchBundle\Mapper\MapperInterface to handle custom field mappings:
      use Becklyn\SearchBundle\Mapper\MapperInterface;
      
      class CustomMapper implements MapperInterface
      {
          public function map($entity): array
          {
              return [
                  'custom_field' => $entity->getCustomValue(),
              ];
          }
      }
      
    • Register in services.yaml:
      services:
          App\Mapper\CustomMapper:
              tags:
                  - { name: 'becklyn.search.mapper', entity: 'Product' }
      
  2. Event Listeners:

    • Subscribe to IndexEntityEvent or SearchEvent for custom logic:
      use Becklyn\SearchBundle\Event\SearchEvent;
      
      class CustomSearchListener
      {
          public function onSearch(SearchEvent $event)
          {
              $event->getQuery()->addParam('custom_param', 'value');
          }
      }
      
    • Tag in services.yaml:
      services:
          App\Listener\CustomSearchListener:
              tags:
                  - { name: 'kernel.event_listener', event: 'becklyn.search.query', method: 'onSearch' }
      
  3. Async Indexing:

    • Use Symfony Messenger for background indexing:
      use Becklyn\SearchBundle\Message\IndexEntityMessage;
      
      $bus->dispatch(new IndexEntityMessage($entity));
      
    • Configure transport in config/packages/messenger.yaml.
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