博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
【Laravel】为Eloquent 模型设置全局作用域和局部作用域进行查询
阅读量:6146 次
发布时间:2019-06-21

本文共 2454 字,大约阅读时间需要 8 分钟。

全局作用域

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

以 User 模型类为例,我们在系统中可能只想针对已经验证过邮箱的用户进行操作,在没有介绍「作用域」之前,可能你会在应用中到处编写这样的代码:

$users = User::whereNotNull('email_verified_at')->...

通过全局作用域类实现

要实现「全局作用域」,首先需要编写一个实现 Illuminate\Database\Eloquent\Scope 接口的全局作用域类,这里我们将其命名为 EmailVerifiedAtScope,并将其放到 app/Scopes 目录下:

whereNotNull('email_verified_at'); }}

在这个全局作用域类中,只需要实现 apply 方法即可,在该方法中,在查询构建器上应用过滤器方法并将其返回。

然后,我们需要将这个全局作用域类注册到 User 模型类上,这样,在 User 模型类上进行查询的时候才可以应用相应的过滤条件。这个工作可以通过在 User 模型类中重写父类的 boot 方法来完成:

protected static function boot(){    parent::boot();    static::addGlobalScope(new EmailVerifiedAtScope());}

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

通过匿名函数实现

如果你觉得编写一个「全局作用域」类很麻烦,过滤逻辑又很简单,还可以在模型类的 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();   # 移除多个类/匿名函数

局部作用域

所谓「局部作用域」,指的是预置过滤器在对应模型类的指定查询中生效,与「全局作用域」不同,「局部作用域」需要额外指定才能生效,但是相应的,也更加灵活,可以适用于不同场景。

「局部作用域」的实现也比较简单,在需要应用它的模型类中定义一个过滤器方法即可。该方法需要以 scope 开头,然后附加该过滤器的名称,以文章列表页显示最流行文章为例(按照浏览数逆序),可以在 Post 模型类中编写一个 scopePopular 方法:

public function scopePopular(Builder $query){    return $query->where('views', '>', '0')->orderBy('views', 'desc');}

而在文章详情页,我们希望展示的是已发布的文章详情,如果文章没有发布,返回 404,因此我们再定义一个「局部作用域」方法 scopeActive

public function scopeActive(Builder $query){    return $query->where('status', Post::ACTIVED);}

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

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

动态作用域

此外,Eloquent 模型类还支持「动态作用域」,所谓动态作用域指的是在查询过程中动态设置预置过滤器的查询条件,动态作用域和局部作用域类似,过滤器方法名同样以 scope 开头,只不过可以通过额外参数指定查询条件,比如我要在文章中查询指定类型的文章,可以通过在 Post 模型类中定义如下方法:

public function scopeOfType(Builder $query, $type){    return $query->where('type', $type);}

这样,在查询指定类型的文章时,就可以这么实现:

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

 

转载于:https://www.cnblogs.com/jxl1996/p/10338905.html

你可能感兴趣的文章
『流畅的Python』第9章笔记_对象
查看>>
结构化数据、半结构化数据和非结构化数据
查看>>
SQLServer 2014 本地机房HA+灾备机房DR解决方案
查看>>
centos7安装配置mysql5.6
查看>>
反爬虫:利用ASP.NET MVC的Filter和缓存(入坑出坑)
查看>>
SaaS技术栈的走势
查看>>
nunit单元测试详解
查看>>
WPF 定时器DispatcherTimer+GetCursorPos 的使用,动态查看屏幕上任一点坐标
查看>>
互联网支付系统概要设计
查看>>
ASP.NET 的ClientIDMode属性
查看>>
shell脚本案例分享 - 业务系统日志自定义保留或删除需求
查看>>
DirectShow基础编程 最简单transform filter 编写步骤
查看>>
Android studio之更改快捷键及自动导包
查看>>
学习ios【1】Objective-C 基本语法
查看>>
Delphi与C语言类型转换对照
查看>>
VS 类快捷键
查看>>
/etc/motd and /etc/issue
查看>>
Java编程的逻辑 (31) - 剖析Arrays
查看>>
使用 Spring Boot 快速构建 Spring 框架应用,PropertyPlaceholderConfigurer
查看>>
python redis使用心得
查看>>