Local Query Scopes

A local scope names a reusable constraint. Since Laravel 12.4 2,157 you mark a protected model method with #[Scope] and call it by its own name; the older public scopeInStock(), called as inStock(), still works. Product has a second scope, priceBetween(Builder $query, float $min, float $max), whose body is one whereBetween():

app/Models/Product.php, a local scopePHP
#[Scope]
protected function inStock(Builder $query): void
{
    $query->where('stock', '>', 0);
}
Calling the scopesSQL
use App\Models\Product;
echo Product::inStock()->orWhere->priceBetween(0, 5)->count(), "\n";
Output
-- select count(*) as `aggregate` from `products` where (`stock` > 0 or (`price` between 0 and
5)) and `products`.`deleted_at` is null
10

Scopes chain like builder methods (Product::inStock()->priceBetween(30, 45)->get()). The higher-order orWhere->priceBetween() joined the second scope with or, and Eloquent parenthesized the query's conditions before appending the soft-delete clause, so the or cannot leak past it; callScope() does the same for a scope whose own conditions contain an or. Name scopes in the business's vocabulary ("in stock", "overdue").