本文目录导读:

在 PHP 中,查询作用域(Query Scope)是 Laravel Eloquent ORM 的核心特性之一,下面我来详细介绍如何定义和使用查询作用域:
本地作用域(Local Scopes)
基本定义方法
在模型中定义以 scope 开头的方法:
<?php
namespace App\Models;
use Illuminate\Database\Eloquent\Model;
use Illuminate\Database\Eloquent\Builder;
class User extends Model
{
/**
* 定义本地作用域
* 方法名:scope + 作用域名(驼峰式)
*/
public function scopeActive($query)
{
return $query->where('status', 'active');
}
public function scopeAdmin($query)
{
return $query->where('role', 'admin');
}
public function scopeOfType($query, $type)
{
return $query->where('type', $type);
}
}
使用本地作用域
// 基本使用
$activeUsers = User::active()->get();
// 链式调用
$activeAdmins = User::active()->admin()->get();
// 带参数的作用域
$users = User::ofType('premium')->get();
// 组合使用
$recentActiveUsers = User::active()
->where('created_at', '>', now()->subDays(30))
->orderBy('created_at', 'desc')
->get();
动态作用域(带参数)
class Product extends Model
{
/**
* 带多个参数的作用域
*/
public function scopePriceBetween($query, $min, $max)
{
return $query->whereBetween('price', [$min, $max]);
}
public function scopeSearch($query, $term, $columns = ['name', 'description'])
{
return $query->where(function ($q) use ($term, $columns) {
foreach ($columns as $column) {
$q->orWhere($column, 'LIKE', "%{$term}%");
}
});
}
}
// 使用动态作用域
$products = Product::priceBetween(100, 500)->get();
$results = Product::search('keyword', ['name', 'sku'])->get();
全局作用域(Global Scopes)
全局作用域会在所有查询中自动应用:
使用匿名函数
class User extends Model
{
protected static function booted()
{
static::addGlobalScope('active', function (Builder $builder) {
$builder->where('status', 'active');
});
}
}
创建作用域类
<?php
namespace App\Scopes;
use Illuminate\Database\Eloquent\Builder;
use Illuminate\Database\Eloquent\Model;
use Illuminate\Database\Eloquent\Scope;
class ActiveScope implements Scope
{
public function apply(Builder $builder, Model $model)
{
$builder->where('status', 'active');
}
}
在模型中使用全局作用域类
class User extends Model
{
protected static function booted()
{
static::addGlobalScope(new ActiveScope);
}
// 移除全局作用域的方法
public static function withoutGlobalScope($scope)
{
return static::withoutGlobalScope($scope);
}
}
完整的实际示例
<?php
namespace App\Models;
use Illuminate\Database\Eloquent\Model;
use Illuminate\Database\Eloquent\Builder;
use App\Scopes\ActiveScope;
class Post extends Model
{
protected $table = 'posts';
// 添加全局作用域
protected static function booted()
{
static::addGlobalScope(new ActiveScope);
}
/**
* 查发布状态的文章
*/
public function scopePublished($query)
{
return $query->where('status', 'published');
}
/**
* 按作者筛选
*/
public function scopeByAuthor($query, $authorId)
{
return $query->where('author_id', $authorId);
}
/**
* 获取热门文章
*/
public function scopePopular($query, $minViews = 1000)
{
return $query->where('views', '>=', $minViews)
->orderBy('views', 'desc');
}
/**
* 带排序的作用域
*/
public function scopeSorted($query, $sortBy = 'created_at', $order = 'desc')
{
return $query->orderBy($sortBy, $order);
}
}
使用示例
// 控制器中使用
class PostController extends Controller
{
public function index(Request $request)
{
$posts = Post::query()
->published()
->popular(500)
->byAuthor($request->user()->id)
->paginate(10);
return view('posts.index', compact('posts'));
}
}
高级技巧
动态添加查询条件
class Product extends Model
{
public function scopeFilter($query, array $filters)
{
return $query
->when($filters['category'] ?? null, function ($query, $category) {
return $query->where('category', $category);
})
->when($filters['min_price'] ?? null, function ($query, $minPrice) {
return $query->where('price', '>=', $minPrice);
})
->when($filters['search'] ?? null, function ($query, $search) {
return $query->where('name', 'like', "%{$search}%");
});
}
}
关键要点
- 命名约定:作用域方法必须以
scope开头,使用时省略scope前缀 - 返回值:必须返回查询构建器实例(
$query) - 可链式调用:作用域可以相互链接
- 参数传递:第一个参数是
$query,后续是业务参数 - 避免逻辑重复:统一在作用域中处理常见过滤条件
注意事项
// ✅ 正确方式
public function scopeActive($query) { return $query->where('status', 1); }
User::active()->get();
// ❌ 错误方式
public function scopeActive($query) { $query->where('status', 1); } // 忘记 return
这样的设计让代码更加清晰、可维护,避免在控制器中重复编写复杂的查询逻辑。
版权声明:NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
CBA直播
CBA直播
CBA直播
CBA直播
CBA直播
CBA直播
CBA直播
CBA直播
CBA直播
CBA直播
CBA直播
CBA直播
CBA直播
CBA直播
CBA直播
CBA直播
CBA直播
CBA直播
足球直播
足球直播
足球直播
足球直播
足球直播
足球直播
足球直播
足球直播
足球直播
足球直播
足球直播
足球直播
足球直播
足球直播
足球直播
足球直播
足球直播
足球直播
英超直播
英超直播
英超直播
英超直播
英超直播
英超直播
英超直播
英超直播
英超直播
英超直播
英超直播
英超直播
英超直播
英超直播
英超直播
英超直播
英超直播
英超直播