Laravel5.8
  1. 安装配置及核心内容
  2. 框架基础
  3. 进阶知识
  4. 数据库相关
    1. Laravel - 数据库相关 - 简介与配置
    2. Laravel - 数据库相关 - 原生 SQL 操作
    3. Laravel - 数据库相关 - 查询构造器
    4. Laravel - 数据库相关 - 分页
    5. Laravel - 数据库相关 - 数据迁移
    6. Laravel - 数据库相关 - 数据填充
    7. Laravel - 数据库相关 - redis
    8. Laravel - Eloquent 模型 - 入门
    9. Laravel - Eloquent 模型 - 查询作用域(全局,本地,动态)
    10. Laravel - Eloquent 模型 - 事件与监听方法
    11. Laravel - Eloquent 模型 - 关联关系
    12. Laravel - Eloquent 模型 - 关联查询
    13. Laravel - Eloquent 模型 - 访问器和修改器

Laravel - Eloquent 模型 - 查询作用域(全局,本地,动态)

程序员日记      2019-09-09

全局作用域

创建全局作用域的类

<?php
namespace App\Scopes;
use Illuminate\Database\Eloquent\Scope;
use Illuminate\Database\Eloquent\Model;
use Illuminate\Database\Eloquent\Builder;
class AgeScope implements Scope
{
    /**
     * 应用作用域到给定的Eloquent查询构建器.
     */
    public function apply(Builder $builder, Model $model)
    {
        return $builder->where('age', '>', 200);
    }
}

说明

1.需要实现 Illuminate\Database\Eloquent\Scope 接口

2.该接口要求你实现一个方法:apply,需要的话可以在 apply 方法中添加 where 条件到查询。


应用全局作用域

<?php
namespace App;
use App\Scopes\AgeScope;
use Illuminate\Database\Eloquent\Model;
class User extends Model
{
    /**
     * 模型的“启动”方法.
     */
    protected static function boot()
    {
        parent::boot();
        static::addGlobalScope(new AgeScope);
    }
}

说明

1.重写给定模型的 boot 方法并使用 addGlobalScope 方法

2.添加作用域后,如果使用 User::all() 查询则会生成如下 SQL 语句

select * from `users` where `age` > 200


匿名的全局作用域

<?php
namespace App;
use Illuminate\Database\Eloquent\Model;
use Illuminate\Database\Eloquent\Builder;
class User extends Model{
    protected static function boot()
    {
        parent::boot();
        static::addGlobalScope('age', function(Builder $builder) {
            $builder->where('age', '>', 200);
        });
    }
}


给定的查询移除全局作用域

// 全局作用域类
User::withoutGlobalScope(AgeScope::class)->get();
// 全局作用域闭包
User::withoutGlobalScope('age')->get();
// 移除所有全局作用域
User::withoutGlobalScopes()->get();
//移除某些全局作用域   
User::withoutGlobalScopes([FirstScope::class, SecondScope::class])->get();

本地作用域

在模型中使用scope前缀方法创建本地作用域的查询

<?php
namespace App;
use Illuminate\Database\Eloquent\Model;
class User extends Model
{
    /**
     * 只包含活跃用户的查询作用域
     *
     * @return \Illuminate\Database\Eloquent\Builder
     */
    public function scopePopular($query)
    {
        return $query->where('votes', '>', 100);
    }
    /**
     * 只包含激活用户的查询作用域
     *
     * @return \Illuminate\Database\Eloquent\Builder
     */
    public function scopeActive($query)
    {
        return $query->where('active', 1);
    }
}

说明

定义这样的一个本地作用域,只需简单在对应 Eloquent 模型方法前加上一个 scope 前缀。


使用本地作用域

//使用本地作用域,方法不需要带scope前缀
$users = App\User::popular()->active()->orderBy('created_at')->get();
//在闭包里使用
$users = App\User::popular()->orWhere(function (Builder $query) {
    $query->active();
})->get();
//高阶方法
$users = App\User::popular()->orWhere->active()->get();

说明

调用时不需要scope前缀


动态作用域

创建动态作用域

<?php
namespace App;
use Illuminate\Database\Eloquent\Model;
class User extends Model
{
    /**
     * 让查询只包含给定类型的用户
     */
    public function scopeOfType($query, $type)
    {
        return $query->where('type', $type);
    }
}

说明

只需要将额外的参数传递进本地作用域即可

$users = App\User::ofType('admin')->get();