agog/osmose
Osmose is a Laravel package for elegantly filtering Eloquent queries via dedicated filter classes. Generate filters with an artisan command, define rules in a residue() array, and apply them with sieve() using built-in direct, callback, and relationship drivers.
Filter classes, decoupling business rules from controllers. Follows Laravel’s service-layer patterns.DirectFilter, CallbackFilter, RelationshipFilter) and allows for future additions via the OsmoseFilterInterface.osmose() helper reduces verbosity for simple use cases, though explicit sieve() calls offer more control.osmose:make-filter) scaffolds filters in seconds. Minimal configuration required for basic use.Resource::collection()) and pagination (->paginate()).residue()/bound() methods require understanding of rule syntax.with() eager loading).where clauses).->toSql() to inspect generated SQL.bound() rules always execute, which may conflict with optional filters.created_at ranges).?gender= or ?role= with no value).UserFilter, ProductFilter) or domain-agnostic (e.g., AdminFilter for all admin queries)?RelationshipFilter with large datasets.FullTextFilter for search)? If so, evaluate maintainability of the Driver interface.residue() logic vs. integration tests for query correctness?QueryBuilder assertions (e.g., expectsQuery() in Pest)./users?role=admin&status=active).if ($request->has('gender')) with GenderFilter).| Phase | Action | Tools/Commands |
|---|---|---|
| Assessment | Audit existing filters (e.g., manual where clauses in controllers). |
Search for ->where( in codebase. |
| Scaffolding | Generate filter classes for critical models. | php artisan osmose:make-filter UserFilter |
| Incremental | Replace one controller’s filtering logic at a time. | Start with high-impact endpoints (e.g., dashboards). |
| Global | Adopt osmose() helper for simple cases (e.g., public APIs). |
Publish config if using custom namespaces. |
| Optimization | Profile and optimize slow filters (e.g., add with() for relationships). |
Laravel Debugbar, Xdebug. |
belongsTo, hasMany, belongsToMany).deleted_at if the model uses it.FormRequest for input validation before filtering.spatie/laravel-api or fractal.where clauses (e.g., ?status=active).roles.name).?search=term with full-text search).bound(): Enforce mandatory filters (e.g., admin-only queries).osmose(): Shortcut for low-complexity endpoints.App\Http\Filters, reducing controller bloat.residue() must return array).CallbackFilter can scatter logic across many files.PascalCase for filters (e.g., ActiveUserFilter).residue() explaining available query params.->toSql() or dd($filter->sieve(Model::class)->getQuery()).$request->all() before filtering to verify input.residue() keys match request params exactly (case-sensitive).DB::enableQueryLog().spatie/laravel-query-builder if osmose lacks features.sieve() in try-catch for invalid inputs.Rule::in(['admin', 'user']) for role params).->cursor() for pagination or ->chunk() for batch processing.Cache::remember('filtered_users', 5, fn() => $filter->sieve(User::class)->get())).gender, role_id) are indexed.How can I help you explore Laravel packages today?