## Getting Started
### Minimal Setup
1. **Installation**:
```bash
composer require baks-dev/search
php artisan vendor:publish --provider="BaksDev\Search\SearchServiceProvider" --tag="search-config"
config/search.php) and migrations (if any).Basic Configuration:
config/search.php to define:
'engines' => [
'default' => [
'driver' => 'meilisearch', // or 'elasticsearch', 'algolia', etc.
'config' => [
'host' => env('SEARCH_HOST'),
'api_key' => env('SEARCH_API_KEY'),
],
],
],
.env:
SEARCH_HOST=localhost:7700
SEARCH_API_KEY=your_api_key
First Search Query:
use BaksDev\Search\Facades\Search;
$results = Search::query('laravel')->engine('default')->search();
score, id).Indexing a Model:
use BaksDev\Search\Traits\Searchable;
class Post extends Model
{
use Searchable;
protected $searchable = [
'columns' => ['title', 'body'],
'engine' => 'default',
];
}
php artisan search:index to index all Post models.config/search.php for engine settings.BaksDev\Search\Facades\Search for direct queries.Searchable for Eloquent model integration.php artisan search:* for CLI tools (e.g., indexing, reindexing).Searching, SearchResult for custom logic.// Search posts by title/body
$posts = Search::query('laravel framework')
->engine('default')
->filter('category', 'tutorial')
->paginate(10)
->get();
score and id for sorting/filtering.Trait-Based:
class Product extends Model
{
use Searchable;
protected $searchable = [
'columns' => ['name', 'description', 'sku'],
'engine' => 'algolia',
'settings' => [
'searchableAttributes' => ['name', 'description'],
],
];
}
saved, deleted).Manual Indexing:
// Index a single model
$post = Post::find(1);
$post->searchableIndex();
// Reindex all models
php artisan search:reindex Post
Fluent Interface:
$results = Search::query('php')
->engine('elasticsearch')
->filter('published', true)
->sortBy('created_at', 'desc')
->limit(20)
->search();
Dynamic Filters:
$filters = request()->input('filters', []);
$results = Search::query($q)
->addFilters($filters)
->search();
Search::engine('meilisearch')->typoTolerance()->search();
Search::engine('elasticsearch')->highlight('body')->search();
// Pagination
$results = Search::query($q)->paginate(15);
// Cursor-based (for large datasets)
$results = Search::query($q)->cursor()->limit(50)->search();
Extend the package by creating a custom driver:
namespace App\Search\Engines;
use BaksDev\Search\Contracts\Engine;
class CustomEngine implements Engine
{
public function search(string $query, array $options): array
{
// Custom logic
}
}
Register in config/search.php:
'engines' => [
'custom' => [
'driver' => \App\Search\Engines\CustomEngine::class,
],
],
Listen for search events to modify results or log queries:
// app/Providers/EventServiceProvider.php
protected $listen = [
\BaksDev\Search\Events\Searching::class => [
\App\Listeners\LogSearchQuery::class,
],
];
Engine-Specific Quirks:
primaryKey in $searchable if not id.
protected $searchable = [
'columns' => ['title'],
'primaryKey' => 'slug',
];
analyzer settings for non-English text.
'settings' => [
'analysis' => [
'analyzer' => ['custom_analyzer' => [...]],
],
],
Rate Limiting:
->throttle(100) to batch queries:
Search::query($q)->throttle(100)->search();
Index Sync Delays:
->sync() to force sync:
$post->searchableSync();
Case Sensitivity:
Search::query($q)->caseSensitive()->search(); // Meilisearch/Elasticsearch
Memory Limits:
php artisan search:reindex Post --chunk=100
Enable Logging:
Search::enableLogging();
storage/logs/search.log.Raw Engine Queries:
$rawQuery = Search::query($q)->getRawQuery();
Test Locally:
# docker-compose.yml
services:
meilisearch:
image: getmeili/meilisearch:v1.4
ports:
- "7700:7700"
Common Errors:
config/search.php and environment variables.php artisan search:reindex Model to ensure indices exist.search.timeout in config (default: 5 seconds).Selective Indexing:
protected $searchable = [
'columns' => ['title', 'tags'], // Exclude heavy fields like 'body'
];
Caching Results:
$results = Cache::remember("search_{$q}", now()->addHours(1), function() use ($q) {
return Search::query($q)->search();
});
Async Indexing:
Post::chunk(200, function ($posts) {
Search::queueIndex($posts);
});
Engine Optimization:
searchableAttributes and displayedAttributes to optimize.index.mapping for better performance.Custom Scoring:
SearchBuilder:
namespace App\Search;
use BaksDev\Search\SearchBuilder;
class CustomSearchBuilder extends SearchBuilder
{
protected function applyCustomScoring(array $results): array
{
// Modify scores based on business logic
return $results;
}
}
AppServiceProvider:
Search::extend('custom', function () {
return new CustomSearchBuilder();
});
Pre/Post-Processors:
Search::preProcess(function ($query) {
// Modify query object
});
Search::postProcess
How can I help you explore Laravel packages today?