Installation
composer require splash/scopes
Add the service provider to config/app.php:
Splash\Scopes\ScopesServiceProvider::class,
Basic Usage Define a scope in a model:
use Splash\Scopes\Scope;
class User extends Model
{
public function scopeActive($query)
{
return $query->where('active', true);
}
}
Apply it in a query:
$activeUsers = User::active()->get();
First Use Case
scopePublished(), scopeArchived()).User::scopeByRole($request->role)->get()).Use scope* methods for reusable filters:
// Model: User.php
public function scopeByRole($query, $role)
{
return $query->where('role', $role);
}
// Usage:
User::byRole('admin')->get();
Apply scopes conditionally (e.g., based on auth or request):
public function scopeForAdmin($query)
{
if (auth()->check()) {
return $query->where('admin', true);
}
return $query;
}
For always-applied filters (e.g., soft deletes):
use Illuminate\Database\Eloquent\Scope;
class ActiveScope implements Scope
{
public function apply(Builder $builder, Model $model)
{
$builder->where('active', true);
}
}
// Register in model's boot():
protected static function boot()
{
static::addGlobalScope(new ActiveScope);
}
Extend QueryBuilder for non-model queries:
use Splash\Scopes\QueryBuilder;
$query = QueryBuilder::for(User::class)
->scope('active')
->scope('byRole', 'admin')
->get();
Use scopes in API responses (e.g., ?filter=active):
// Route:
Route::get('/users', function () {
return User::when(request('filter') === 'active', fn($q) => $q->active())
->get();
});
Naming Conflicts
Avoid naming scopes like scopeWhere* (reserved for Laravel’s dynamic scopes). Stick to scope* or scopeBy*.
Global Scope Overhead
Global scopes run on every query. Use sparingly—profile with DB::enableQueryLog().
Caching Issues Scopes bypass Laravel’s query cache. Cache results manually if needed:
$users = Cache::remember('active_users', now()->addHour(), fn() => User::active()->get());
DB::enableQueryLog();
User::active()->get();
dd(DB::getQueryLog());
// Bad: Assumes order
User::active()->byRole('admin');
// Good: Explicit
User::byRole('admin')->active();
Custom Scope Logic
Extend Splash\Scopes\Scope for complex behavior (e.g., multi-table joins).
Request-Based Scopes Use middleware to attach scopes dynamically:
// Middleware: ApplyUserScopes.php
public function handle($request, Closure $next)
{
User::addGlobalScope(new RequestScope($request));
return $next($request);
}
Testing Mock scopes in tests:
$scope = $this->partialMockFor(User::class, ['scopeActive']);
$scope->scopeActive()->willReturn($query);
with():
User::active()->with('posts')->get();
active) are indexed for large datasets.How can I help you explore Laravel packages today?