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

Seal Laravel Package

cmsig/seal

SEAL Core (cmsig/seal) is a Search Engine Abstraction Layer inspired by Doctrine DBAL and Flysystem. Provides a unified API and schema for indexing, searching, and filtering across multiple search engines. Part of the cmsig/search project.

View on GitHub
Deep Wiki
Context7

Getting Started

Minimal Setup

  1. Install the Package

    composer require cmsig/seal
    

    Ensure your project uses PHP 8.1+ (check composer.json constraints).

  2. Configure a Search Engine Define a supported adapter (e.g., Elasticsearch, OpenSearch, or Meilisearch) in config/seal.php:

    'engines' => [
        'default' => [
            'driver' => 'elasticsearch',
            'hosts' => ['http://localhost:9200'],
            'index' => 'your_index_name',
        ],
    ],
    
  3. First Use Case: Basic Search Inject the SearchEngine facade or bind it in a service provider:

    use CMSIG\Search\SearchEngine;
    
    $results = SearchEngine::search('default', 'query');
    
  4. Documentation Start with the official docs for schema definitions, indexing, and advanced queries.


Implementation Patterns

Core Workflows

1. Schema Definition

Define your index schema in a Laravel migration or service class:

use CMSIG\Search\Schema\Builder;

$schema = Builder::create()
    ->addTextField('title')
    ->addKeywordField('category')
    ->addIntegerField('views')
    ->build();
SearchEngine::createIndex('default', $schema);

2. Indexing Data

Use the Indexer to push data to the search engine:

$indexer = SearchEngine::indexer('default');
$indexer->index([
    'id' => 1,
    'title' => 'Laravel SEAL Guide',
    'category' => 'tutorial',
    'views' => 1000,
]);

3. Searching with Filters

Leverage the query builder for complex searches:

$results = SearchEngine::search('default')
    ->query('laravel')
    ->filter('category', 'tutorial')
    ->sortBy('views', 'desc')
    ->limit(10)
    ->get();

4. Pagination

Integrate with Laravel’s pagination:

$results = SearchEngine::search('default')
    ->query('guide')
    ->paginate(15); // Returns a LengthAwarePaginator

5. Bulk Operations

Use batch indexing for performance:

$indexer = SearchEngine::indexer('default');
$indexer->bulkIndex([
    ['id' => 1, 'title' => 'Post 1'],
    ['id' => 2, 'title' => 'Post 2'],
]);

Integration Tips

Laravel Service Providers

Bind the SearchEngine to the container for dependency injection:

public function register()
{
    $this->app->bind('search', function ($app) {
        return new SearchEngine(config('seal.engines.default'));
    });
}

Eloquent Models

Extend Eloquent models with searchable traits or repositories:

use CMSIG\Search\Eloquent\Searchable;

class Post extends Model
{
    use Searchable;

    protected $searchable = ['title', 'content'];
}

API Resources

Transform search results into API responses:

public function toArray($request)
{
    return [
        'data' => $this->searchResults->map(fn ($item) => [
            'id' => $item['id'],
            'title' => $item['title'],
        ]),
    ];
}

Gotchas and Tips

Pitfalls

  1. Schema Mismatches

    • Issue: Updating a schema after indexing may cause errors.
    • Fix: Use SearchEngine::updateIndex() or recreate the index with a new schema.
    • Tip: Version your schemas (e.g., index_v2) and migrate data incrementally.
  2. Connection Timeouts

    • Issue: Search engines may time out during bulk operations.
    • Fix: Configure retries in the engine adapter or chunk your bulk operations:
      $indexer->bulkIndex($posts->chunk(100));
      
  3. Case Sensitivity

    • Issue: Keyword fields default to case-sensitive matching.
    • Fix: Explicitly configure case insensitivity:
      ->addKeywordField('category')->caseInsensitive()
      
  4. Pagination Conflicts

    • Issue: Laravel’s paginate() may conflict with search engine pagination.
    • Fix: Use ->get() for raw results or manually paginate:
      $results = SearchEngine::search('default')->query('test')->limit(10)->offset(20)->get();
      
  5. Missing Dependencies

    • Issue: Adapters (e.g., elasticsearch) require additional packages (e.g., elasticsearch/elasticsearch).
    • Fix: Install via Composer:
      composer require elasticsearch/elasticsearch
      

Debugging

  1. Enable Logging Configure the search engine to log queries:

    'engines' => [
        'default' => [
            'driver' => 'elasticsearch',
            'logger' => \Monolog\Logger::create('seal'),
        ],
    ],
    
  2. Raw Query Inspection Access the underlying query for debugging:

    $query = SearchEngine::search('default')->query('test')->getQuery();
    dd($query->toArray());
    
  3. Adapter-Specific Tools

    • Elasticsearch: Use curl or Kibana to inspect indices.
    • Meilisearch: Use the meilisearch CLI or dashboard.

Extension Points

  1. Custom Adapters Extend CMSIG\Search\Adapter\AbstractAdapter to support new search engines:

    class CustomAdapter extends AbstractAdapter
    {
        public function search($query, array $options = [])
        {
            // Implement custom logic
        }
    }
    
  2. Query Builders Extend CMSIG\Search\Query\Builder for domain-specific queries:

    class PostQueryBuilder extends Builder
    {
        public function byAuthor($author)
        {
            return $this->filter('author', $author);
        }
    }
    
  3. Schema Extensions Add custom field types by extending CMSIG\Search\Schema\Field:

    class CustomField extends Field
    {
        public function getType(): string
        {
            return 'custom';
        }
    }
    
  4. Event Listeners Listen to search events (e.g., IndexCreated, DocumentIndexed) for analytics or notifications:

    SearchEngine::listen('document.indexed', function ($event) {
        Log::info("Indexed document: {$event->document['id']}");
    });
    

Configuration Quirks

  1. Default Engine Always specify a default engine in config/seal.php to avoid runtime errors.

  2. Index Naming Use lowercase, snake_case for index names to avoid issues with some search engines.

  3. Field Mapping Explicitly map Eloquent fields to search fields to avoid ambiguity:

    protected $searchable = [
        'title' => 'search_title',
        'body' => 'search_content',
    ];
    
  4. Environment-Specific Config Use Laravel’s config caching or environment variables for dynamic engine settings:

    'engines' => [
        'default' => [
            'hosts' => env('SEARCH_HOSTS', ['http://localhost:9200']),
        ],
    ],
    
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.
besmartand-pro/php-quality-config
sentix/ai-chatbot
codifyo/ts-generator-bundle
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