laravel-global-search / global-search
A comprehensive Laravel package for global search functionality with Meilisearch integration, multi-tenancy support, and advanced features.
Installs: 54
Dependents: 0
Suggesters: 0
Security: 0
Stars: 0
Watchers: 0
Forks: 0
Open Issues: 0
pkg:composer/laravel-global-search/global-search
Requires
- php: ^8.3
- ext-curl: *
- ext-json: *
- guzzlehttp/guzzle: ^7.0
- illuminate/cache: ^10.0|^11.0|^12.0
- illuminate/console: ^10.0|^11.0|^12.0
- illuminate/contracts: ^10.0|^11.0|^12.0
- illuminate/database: ^10.0|^11.0|^12.0
- illuminate/http: ^10.0|^11.0|^12.0
- illuminate/queue: ^10.0|^11.0|^12.0
- illuminate/support: ^10.0|^11.0|^12.0
- meilisearch/meilisearch-php: ^1.0
Requires (Dev)
- orchestra/testbench: ^8.0|^9.0
- phpunit/phpunit: ^10.0
README
A powerful, fully configurable Laravel package for global search with Meilisearch integration and multi-tenancy support.
v1.1.29: 🚀 Fully Dynamic & Configurable - Zero hardcoded values! Every aspect is user-configurable via environment variables.
📖 Documentation
- Configuration Guide - Complete reference for all 30+ configuration options
- Changelog - Version history and upgrade guides
🚀 Quick Start
1. Install
composer require laravel-global-search/global-search
2. Configure
# Publish config php artisan vendor:publish --tag=global-search-config # Add to .env MEILISEARCH_HOST=http://localhost:7700 MEILISEARCH_KEY=your-master-key
3. Setup Models
Edit config/global-search.php:
'mappings' => [ [ 'model' => App\Models\User::class, 'index' => 'users', 'primaryKey' => 'id', 'fields' => ['id', 'name', 'email', 'phone', 'created_at'], 'filterable' => ['user_type', 'status', 'created_at'], 'sortable' => ['name', 'created_at', 'updated_at'], 'computed' => [ 'url' => fn($model) => route('users.show', $model->id), ], ], ],
4. Sync Settings & Index
# Step 1: Sync settings to Meilisearch (REQUIRED for filters/sorting) php artisan search:sync-settings # Step 2: Index your data php artisan search:reindex # Step 3: Process the queue php artisan queue:work --stop-when-empty
⚠️ Important: Always run
search:sync-settingsbefore indexing when you:
- First set up the package
- Change filterable/sortable attributes in config
- Add new indexes or modify index settings
Without syncing settings, filters and sorting will NOT work!
// Search via API GET /global-search?q=john&limit=10 // Or use the service $results = app('global-search')->search('john');
🎯 Core Features
- 100% Configurable - No hardcoded values, all via config/env
- Multi-Tenancy - Automatic tenant detection and isolation
- Dynamic Limits - Configurable default/max limits
- Smart Caching - Configurable TTL and cache drivers
- Performance Monitoring - Slow query detection and metrics
- Advanced Filtering - Filter by any configured field
- Sorting - Multi-field sorting support
- Job-Based - All operations use background jobs
📊 API Usage
Basic Search
GET /global-search?q=john
With Filters
GET /global-search?q=john&filters[user_type]=Client&filters[status]=1
With Sorting
GET /global-search?q=john&sort[name]=asc&sort[created_at]=desc
With Limit
GET /global-search?q=john&limit=50
Multi-Tenant
# Automatic detection from subdomain GET https://tenant1.yourdomain.com/global-search?q=john # Or specify tenant GET /global-search?q=john&tenant=tenant1
🔧 Configuration
Essential Settings
# Meilisearch MEILISEARCH_HOST=http://localhost:7700 MEILISEARCH_KEY=your-master-key # Limits GLOBAL_SEARCH_DEFAULT_LIMIT=10 GLOBAL_SEARCH_MAX_LIMIT=100 # Cache GLOBAL_SEARCH_CACHE_ENABLED=true GLOBAL_SEARCH_CACHE_TTL=60 # Pipeline GLOBAL_SEARCH_BATCH_SIZE=1000 GLOBAL_SEARCH_CHUNK_SIZE=100 # Multi-Tenancy GLOBAL_SEARCH_TENANT_ENABLED=true
See CONFIGURATION.md for complete options.
🛠️ Commands
# Reindex all data php artisan search:reindex # Sync Meilisearch settings php artisan search:sync-settings # Check health php artisan search:health # View performance metrics php artisan search:performance # Flush all indexes php artisan search:flush
🏢 Multi-Tenancy
Enable in config:
'tenant' => [ 'enabled' => true, 'identifier_column' => 'id', ],
Automatic detection from:
- Subdomain:
tenant1.domain.com - Header:
X-Tenant-ID: tenant1 - Query:
?tenant=tenant1 - Route:
/tenant/{tenant}/... - Auth user:
auth()->user()->tenant_id
🔍 Filtering & Sorting
Configure in config/global-search.php:
'mappings' => [ [ 'model' => App\Models\Product::class, 'index' => 'products', 'filterable' => ['status', 'category', 'price', 'created_at'], 'sortable' => ['price', 'name', 'created_at'], ], ], 'index_settings' => [ 'products' => [ 'filterableAttributes' => ['status', 'category', 'price', 'created_at'], 'sortableAttributes' => ['price', 'name', 'created_at'], 'searchableAttributes' => ['name', 'description', 'sku'], ], ],
Apply settings:
# Step 1: Sync settings first (REQUIRED!) php artisan search:sync-settings # Step 2: Reindex data php artisan search:reindex # Step 3: Process queue php artisan queue:work --stop-when-empty
💡 Tip: After changing any filterable/sortable attributes in your config, always run
search:sync-settingsfirst!
Use in API:
# Filter GET /global-search?q=product&filters[status]=active&filters[category]=electronics # Sort GET /global-search?q=product&sort[price]=asc&sort[created_at]=desc # Pagination (offset + limit) GET /global-search?q=product&limit=20&offset=40 # Combined: Filter + Sort + Pagination GET /global-search?q=product&filters[status]=active&sort[price]=asc&limit=20&offset=0
🎨 Data Transformation
1. Automatic (No code needed)
class User extends Model { // That's it! }
2. Model Method
class User extends Model { public function toSearchableArray(): array { return [ 'id' => $this->id, 'name' => $this->name, 'email' => $this->email, 'full_name' => $this->first_name . ' ' . $this->last_name, ]; } }
3. Config-Based
'mappings' => [ [ 'model' => App\Models\User::class, 'index' => 'users', 'fields' => ['id', 'name', 'email'], 'computed' => [ 'url' => fn($m) => route('users.show', $m->id), 'full_name' => fn($m) => $m->first_name . ' ' . $m->last_name, ], ], ],
🔒 Production Security (IMPORTANT!)
⚠️ The global search endpoint is PUBLIC by default. Secure it in production!
Simple Authentication (Recommended)
Add this to your routes/api.php:
// Protect the search endpoint with authentication Route::middleware(['auth:sanctum'])->group(function () { Route::get('/global-search', function(Request $request) { // Force user's tenant for security $tenant = auth()->user()->tenant_id ?? null; return app(\LaravelGlobalSearch\GlobalSearch\Http\Controllers\GlobalSearchController::class)( $request->merge(['tenant' => $tenant]) ); }); });
Usage with token:
curl -H "Authorization: Bearer YOUR_TOKEN" \ "https://api.yourdomain.com/global-search?q=search"
Or Disable in Production
// routes/api.php - Only enable in development if (!app()->environment('production')) { Route::get('/global-search', [GlobalSearchController::class, '__invoke']); }
💡 For more security options, see CONFIGURATION.md
⚡ Performance Tuning
High-Volume Apps
GLOBAL_SEARCH_BATCH_SIZE=5000 GLOBAL_SEARCH_CHUNK_SIZE=500 GLOBAL_SEARCH_MAX_LIMIT=50 GLOBAL_SEARCH_CACHE_TTL=600
Low-Memory Environments
GLOBAL_SEARCH_BATCH_SIZE=100 GLOBAL_SEARCH_CHUNK_SIZE=10 GLOBAL_SEARCH_MAX_RELATIONSHIP_ITEMS=5
Development
GLOBAL_SEARCH_CACHE_ENABLED=false GLOBAL_SEARCH_LOG_SLOW_QUERIES=true GLOBAL_SEARCH_SLOW_QUERY_THRESHOLD=100
🔧 Troubleshooting
Issue: No search results
# Fix everything
php artisan search:reindex
php artisan queue:work --stop-when-empty
Issue: Filters not working
# Sync settings and reindex
php artisan search:sync-settings
php artisan search:reindex
Issue: Slow queries
# Enable monitoring GLOBAL_SEARCH_LOG_SLOW_QUERIES=true GLOBAL_SEARCH_SLOW_QUERY_THRESHOLD=500
Check logs for slow query warnings.
📦 Response Format
{
"success": true,
"data": {
"hits": [
{
"id": "01j2zp7zgf",
"name": "John Doe",
"email": "john@example.com",
"user_type": "Client",
"url": "/users/01j2zp7zgf",
"_index": "users"
}
],
"meta": {
"total": 1,
"indexes": ["users"],
"query": "john",
"limit": 10,
"tenant": "tenant1",
"duration_ms": 45.23
}
},
"meta": {
"query": "john",
"limit": 10,
"tenant": "tenant1",
"sort": []
}
}
📄 License
MIT License. See LICENSE for details.
🆘 Support
- Configuration: See CONFIGURATION.md
- Changelog: See CHANGELOG.md
- Issues: GitHub Issues
Built with ❤️ for Laravel developers who need powerful, flexible search.