php 局部和全局作用域,一些查询需要在多个地方调用如何解决?用一下ORM全局作用域和局部作用域...

学习链接

Eloquent 模型类提供的「Scope」功能就可以帮我们实现这种优化。「Scope」字面意义上翻译为「作用域」,有点不那么好理解,从功能上来说,把它看作预置的「过滤器」更合适。我们将那些需要在多处调用的查询条件编写过滤器,然后将调用查询代码的地方改为调用过滤器,调用过滤器比编写那些冗长而重复的查询方法更加便捷,可读性也更好。

从调用方式或者过滤器的作用范围来说,可以把「作用域」分为「全局作用域」和「局部作用域」。「作用域」都是围绕模型类展开的,不管是全局作用域还是局部作用域,都是作用到某个模型类上。

全局作用域、

是什么?

指的是预置过滤器在注册该「全局作用域」的模型类的所有查询中生效,不需要指定任何额外条件。

怎么用?

1. 编写 全局作用域类,实现apply 方法

app/Scopes 目录下:创建 全局作用域类: EmailVerifiedAtScope

类中需要 实现Illuminate\Database\Eloquent\Scope 接口

在这个全局作用域类中,只需要实现其中的 apply 方法即可。

namespace App\Scopes;

use Illuminate\Database\Eloquent\Builder;

use Illuminate\Database\Eloquent\Model;

use Illuminate\Database\Eloquent\Scope;

class EmailVerifiedAtScope implements Scope

{

public function apply(Builder $builder, Model $model)

{

return $builder->whereNotNull('email_verified_at');

}

}

2. 注册这个全局作用域类到 指定模型类(重写父类boot方法)

模型类中重写父类的 boot 方法来完成

protected static function boot()

{

parent::boot();

static::addGlobalScope(new EmailVerifiedAtScope());

}

注:boot 方法会在模型类实例化的时候调用。你可以在这里进行一些模型类的初始化操作。

如何调用?

这样,当我们通过 该 模型类进行查询的时候,就会自动应用全局作用域指定的查询条件了

提问:我看你是调用静态类方法,那我可以写闭包吗?

可以。如下:

protected static function boot()

{

parent::boot();

//static::addGlobalScope(new EmailVerifiedAtScope());

static::addGlobalScope('email_verified_at_scope', function (Builder $builder) {

return $builder->whereNotNull('email_verified_at');

});

}

我个别查询不需要全局作用域?移除全局作用域?

如下:withoutGlobalScope

User::withoutGlobalScope(EmailVerifiedAtScope::class)->get(); # 指定类

User::withoutGlobalScope('email_verified_at_scope')->get(); # 匿名函数

User::withoutGlobalScopes()->get(); # 移除所有全局作用域

User::withoutGlobalScopes([FirstScope::class, SecondScope::class])->get(); # 移除多个类/匿名函数

局部作用域

是什么?

更加灵活的作用域,相对的它的使用,是需要手动指定的

如何用?

1. 创建局部作用域,定义模型的过滤器方法

在需要应用它的模型类中定义一个过滤器方法即可。

注意:该方法需要以 scope 开头,然后附加该过滤器的名称。

以文章列表页显示最流行文章为例(按照浏览数逆序),可以在 Post 模型类中编写一个 scopePopular 方法:

public function scopePopular(Builder $query)

{

return $query->where('views', '>', '0')->orderBy('views', 'desc');

}

// 再来一个

public function scopeActive(Builder $query)

{

return $query->where('status', Post::ACTIVED);

}

如何调用?

在模型类上调用「局部作用域」过滤器方法只需调用 scope 之后的过滤器名称即可,Eloquent 底层会通过魔术方法自动调用对应完整方法。

$post = Post::active()->popular()->get();

是否可以传递参数给作用域?动态作用域

与局部作用域相似,只不过多了参数。

也是 scope 开头。

定义

public function scopeOfType(Builder $query, $type)

{

return $query->where('type', $type);

}

调用

$posts = Post::active()->ofType(Post::Article)->get();

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值