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

Eloquence Base Laravel Package

sofa/eloquence-base

View on GitHub
Deep Wiki
Context7

Getting Started

Minimal Setup

  1. Installation:

    composer require sofa/eloquence-base
    

    Publish the config (optional):

    php artisan vendor:publish --provider="Sofa\Eloquence\EloquenceServiceProvider"
    
  2. First Use Case: Extend your Eloquent model to enable Searchable functionality:

    use Sofa\Eloquence\Searchable\SearchableTrait;
    
    class Post extends Model
    {
        use SearchableTrait;
    
        protected $searchable = [
            'columns' => ['title', 'body'], // Fields to search
            'join' => ['author' => 'users'], // Optional: Related tables
        ];
    }
    
  3. Basic Search Query:

    $results = Post::search('laravel')->get();
    

Where to Look First

  • Searchable Documentation (primary focus of this package)
  • config/eloquence.php (for global configuration)
  • app/Models/ (extend your models with traits)

Implementation Patterns

Core Workflows

1. Searchable Queries

  • Basic Search:
    $posts = Post::search('query')->get();
    
  • Advanced Search (with weights):
    $posts = Post::search('query', [
        'weights' => ['title' => 2, 'body' => 1],
    ])->get();
    
  • Search with Joins:
    $posts = Post::search('query', [
        'join' => ['author' => 'users'],
    ])->get();
    

2. Integration with API Resources

Combine with eloquence-mappable to transform search results:

use Sofa\Eloquence\Mappable\MappableTrait;

class PostResource extends JsonResource
{
    public function toArray($request)
    {
        return $this->resource->map(['title', 'excerpt']);
    }
}

3. Validation + Search Workflow

Use eloquence-validable to validate search inputs:

use Sofa\Eloquence\Validable\ValidableTrait;

class PostRequest extends FormRequest
{
    use ValidableTrait;

    public function rules()
    {
        return ['query' => 'required|string|max:255'];
    }
}

4. Meta Data Handling

Pair with eloquence-metable for dynamic metadata:

use Sofa\Eloquence\Metable\MetableTrait;

class Post extends Model
{
    use MetableTrait;

    protected $meta = ['views', 'tags'];
}

5. Mutators for Search Fields

Use eloquence-mutable to preprocess searchable fields:

use Sofa\Eloquence\Mutable\MutableTrait;

class Post extends Model
{
    use MutableTrait;

    protected $mutable = [
        'search_title' => function ($value) {
            return strtolower($value);
        },
    ];
}

Integration Tips

  1. Database Indexing: Ensure searchable columns are indexed for performance:

    Schema::table('posts', function (Blueprint $table) {
        $table->fullText('title', 'body');
    });
    
  2. Caching Search Results: Cache frequent searches (e.g., autocomplete):

    $cacheKey = 'posts_search_' . md5($query);
    $results = Cache::remember($cacheKey, now()->addHours(1), function () use ($query) {
        return Post::search($query)->get();
    });
    
  3. Scopes for Reusability: Create custom scopes in your model:

    public function scopePublished($query)
    {
        return $query->where('published_at', '<=', now());
    }
    
    // Usage:
    Post::search('query')->published()->get();
    
  4. Testing Search Logic: Use Laravel’s testing helpers:

    public function test_search_returns_results()
    {
        $post = Post::factory()->create(['title' => 'Test Post']);
        $results = Post::search('test')->get();
        $this->assertCount(1, $results);
    }
    

Gotchas and Tips

Pitfalls

  1. Full-Text Search Limitations:

    • MySQL’s FULLTEXT index requires a minimum column length (e.g., MIN_LENGTH=4).
    • Fix: Adjust ft_min_word_len in my.cnf or ensure search terms meet the threshold.
  2. Case Sensitivity:

    • Default MySQL FULLTEXT search is case-insensitive, but other databases (e.g., PostgreSQL) may vary.
    • Tip: Use MATCH ... AGAINST ('query' IN NATURAL LANGUAGE MODE) for better control.
  3. Performance with Large Datasets:

    • Searching across millions of records can be slow.
    • Solution: Implement pagination or use database-specific optimizations (e.g., PostgreSQL’s tsvector).
  4. Join Clauses:

    • Incorrect join syntax (e.g., ['author' => 'users']) may break queries.
    • Debug: Check the generated SQL with Post::search('query')->toSql().
  5. Trait Conflicts:

    • Avoid mixing traits with Laravel’s built-in methods (e.g., boot()).
    • Tip: Use protected static function bootSearchable() for initialization.

Debugging

  1. Log Generated Queries:

    DB::enableQueryLog();
    Post::search('query')->get();
    dd(DB::getQueryLog());
    
  2. Validate Searchable Configuration: Ensure $searchable array is correctly defined in your model. Example error:

    BadMethodCallException: Method search() does not exist.
    

    Fix: Verify the trait is properly used and the config is published.

  3. Handle Missing Full-Text Indexes: If you get SQLSTATE[HY000]: General error: 1356 View ... references invalid table(s), ensure your columns are indexed.


Configuration Quirks

  1. Global Searchable Settings: Override defaults in config/eloquence.php:

    'searchable' => [
        'default_columns' => ['title', 'content'],
        'default_join' => [],
    ],
    
  2. Dynamic Column Mapping: Use closures for dynamic searchable columns:

    protected $searchable = [
        'columns' => function () {
            return ['title', 'body', 'tags.' . $this->category];
        },
    ];
    
  3. Excluding Models from Search: Add a skipSearchable method to your model:

    public function skipSearchable()
    {
        return true;
    }
    

Extension Points

  1. Custom Search Engines: Extend the SearchableTrait to support Algolia/Elasticsearch:

    class AlgoliaSearchableTrait
    {
        public function search($query, $options = [])
        {
            return Algolia::search($query, $options);
        }
    }
    
  2. Add Search Metrics: Track search usage with middleware:

    public function handle($request, Closure $next)
    {
        if ($request->has('search')) {
            SearchLog::create(['query' => $request->search]);
        }
        return $next($request);
    }
    
  3. Searchable Events: Dispatch events for search actions:

    use Sofa\Eloquence\Searchable\Events\Searching;
    
    Searching::dispatch($this, $query, $options);
    
  4. Hybrid Search (SQL + External): Combine database search with external APIs:

    public function search($query, $options = [])
    {
        $dbResults = parent::search($query, $options);
        $apiResults = ExternalSearch::search($query);
        return $dbResults->merge($apiResults);
    }
    
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.
milito/query-filter
apiboxsym/user-bundle
apiboxsym/health-check-bundle
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