首页
学习
活动
专区
工具
TVP
发布
精选内容/技术社群/优惠产品,尽在小程序
立即前往

重构whereHas以通过Laravel中的全局作用域使用

在 Laravel 中,whereHas 方法用于在关联模型上添加查询条件。全局作用域(Global Scopes)则是一种在模型上定义全局约束的方式,这些约束会自动应用于模型的所有查询。将 whereHas 与全局作用域结合使用,可以在多个地方重用相同的查询逻辑,从而提高代码的可维护性和可读性。

基础概念

  1. 全局作用域:全局作用域是一个在模型类中定义的静态方法,它接收一个查询构建器实例,并返回修改后的查询构建器实例。全局作用域会自动应用于模型的所有查询。
  2. whereHaswhereHas 方法用于在关联模型上添加查询条件。它允许你在主模型上定义条件,以过滤与其关联的子模型。

相关优势

  • 代码重用:通过全局作用域,可以在多个地方重用相同的查询逻辑,减少重复代码。
  • 可维护性:将查询逻辑封装在全局作用域中,使得代码更加模块化和易于维护。
  • 可读性:全局作用域提供了一种清晰的方式来组织和理解模型的查询逻辑。

类型与应用场景

  • 单一全局作用域:适用于在整个应用中都需要应用的简单查询约束。
  • 复合全局作用域:通过 Scope 类的组合,可以创建更复杂的全局作用域,以满足更复杂的查询需求。

示例代码

假设我们有一个 Post 模型和一个 User 模型,它们之间存在一对多的关系。我们希望在查询帖子时,只获取那些作者活跃的用户发布的帖子。

首先,在 User 模型中定义一个全局作用域:

代码语言:txt
复制
use Illuminate\Database\Eloquent\Builder;
use Illuminate\Database\Eloquent\Model;
use Illuminate\Database\Eloquent\Scope;

class User extends Model
{
    // ...

    public static function boot()
    {
        parent::boot();

        static::addGlobalScope(new ActiveUserScope);
    }
}

class ActiveUserScope implements Scope
{
    public function apply(Builder $builder, Model $model)
    {
        $builder->where('is_active', 1);
    }
}

然后,在 Post 模型中使用 whereHas 方法结合全局作用域:

代码语言:txt
复制
use Illuminate\Database\Eloquent\Model;

class Post extends Model
{
    // ...

    public function user()
    {
        return $this->belongsTo(User::class);
    }

    public function scopeActiveUserPosts($query)
    {
        return $query->whereHas('user');
    }
}

最后,在控制器中使用这个作用域:

代码语言:txt
复制
use App\Models\Post;

class PostController extends Controller
{
    public function index()
    {
        $posts = Post::activeUserPosts()->get();

        return view('posts.index', compact('posts'));
    }
}

遇到的问题及解决方法

如果在重构 whereHas 以通过全局作用域使用时遇到问题,可能是由于以下原因:

  1. 全局作用域未正确注册:确保在模型中正确调用了 addGlobalScope 方法,并且全局作用域类实现了 Scope 接口。
  2. 作用域逻辑错误:检查全局作用域中的 apply 方法,确保它正确地修改了查询构建器实例。
  3. 关联关系配置错误:确保在模型中正确配置了关联关系,并且关联关系的名称与 whereHas 方法中的参数一致。

参考链接

通过以上步骤和示例代码,你应该能够成功地将 whereHas 与全局作用域结合使用,从而提高代码的可维护性和可读性。

页面内容是否对你有帮助?
有帮助
没帮助

相关·内容

样式作用──页面重构模块化设计(一)

样式作用──页面重构模块化设计(一) 由 Ghostzhang 发表于 2010-03-24 18:41 很久没有更新blog了,这段时间实在是发生了很多事,累身累心。...写过程序同学应该都知道,变量是有作用(不知道同学自己去问谷歌,这里就不作解释了),样式定义也同样存在着作用问题,即定义作用范围,很容易就能理解,如下面的p作用: /*作用全局*/...再来说说“作用”,相信大家很容易就会想到“全局”、“公共”这些词,关注过模块化同学应该都知道,网上说得最多一种“模块化”,就是像header、footer这样大区域划分。...最后几点要特别注意: 除了标签选择器之外,哪些类是使用于公共级、栏目级,如.tx_hit{color:#FF0000 !important;}适用范围是公共级,应该放于全局定义。...标签选择器一般属于栏目定义,有时会用于公共级作用域中,除了最基础reset之外,应尽可能少使用在公共级定义 可继承属性定义使用时须注意影响范围,特别是在标签选择器中使用时 同类选择器无加权 接下来内容就是以这个为基础

36440

栏目级作用──页面重构模块化设计(二)

栏目级作用──页面重构模块化设计(二) 由 Ghostzhang 发表于 2010-04-03 14:49 在《样式作用──页面重构模块化设计(一)》,我将样式作用分为了三个部分...简单解释下栏目级(局部公共)和页面级: 页面级可分为两种情况:在多个页面间,页面级作用指针对某一单独页面定义;在同一个页面,页面级作用指针对某一标签定义。它将决定最终页面效果。...栏目级(局部公共)介于全局与单个页面之间一个作用,影响一个栏目(或某区域)。通常以某一类选择符做为开始,包含选择符方式将样式定义限定在某一区域中。...需要消化下内容,决定一个样式定义是属于哪个作用因素有以下两点: 样式定义所在样式文件位置。(同样一个定义,放在不同位置,所影响范围会有所不同。)...另外需要在思维上注意一点,以作用划分,并不意味着有着对应文件,可能有些同学会习惯以为一个作用就应该对应着一个文件。

34830
  • Dockerfile ARG 使用与其作用(scope)探究

    使用 ARG 可以有效复用 Dockerfile。每次镜像更新,只需要动态在 build 命令传入新参数值即可。...0x01 结论 在第一个 FROM 之前所有 ARG , 在所有 FROM 中生效, 仅在 FROM 中生效 在 FROM 后 ARG, 仅在当前 FROM 作用生效。...即尽在当前 阶段 (stage) 生效 对照组解析 在随后 Dockerfile , 只定义了一个变量 image , 并在 FROM 和 stage 重复使用 对照组1: stage1 和 stage11...均在 FROM 中使用了变量 $image: **作用在所有 FROM 成功拉取 FROM $image 并完成 layer 构建 但是在 RUN 无法正确输出结果,即 image 值 alpine...:3.12 对照组2: stage1 vs stage2: 作用在 FROM stage 内部 在 stage2 作用域中声明了 ARG image,且能正确输出结果。

    62620

    Vue style里面使用@import引入外部css, 作用全局解决方案

    问题描述 使用@import引入外部css,作用却是全局 export default { name...background-color: #3982e5; } Add “scoped” attribute to limit CSS to this component only 这句话大家应该是见多了, 我也使用...scoped, 但是使用@import引入外部样式表作用依然是全局,看了一遍@import规则后, 进行初步猜测,难道是@import引入外部样式表错过了scoped style?...又回想到此前看过前端性能优化文章里面都有提到,在生产环境不要使用@import引入css,因为在请求到css中含有@import引入css的话,会发起请求把@importcss引进来,多次请求浪费不必要资源.../static/css/user.css"; 我们只需把@import改成引入外部样式,就可以解决样式是全局问题 <style scoped

    97610

    如何使用Vue嵌套插槽(包括作用插槽)

    作者:Michael Thiessen 译者:前端小智 来源:medium 最近我弄清楚了如何递归地实现嵌套插槽,包括如何使用作用插槽来实现。...看到这里,你或许就可以明白了,我们可以使用此概念并将其应用于我们组件。 相反,我们将递归嵌套组件表示列表。 我们最终将渲染出这样内容。...因此,我们将从“Parent”获取该内容,然后将其渲染到“Grandchild”插槽。 添加作用插槽 与嵌套作用插槽唯一不同是,我们还必须传递作用数据。...如果没有提供插槽,则默认元素内部内容,并像以前一样渲染list[0]。 但是如果我们提供了一个slot,它会将其渲染出来,并通过slot作用将列表项传递给父组件。...这里递归情况类似。 如果我们将插槽传递给v-for,它将在下一个v-for插槽中进行渲染,因此我们得到了嵌套。 它还从作用获取item并将其传递回链。

    5K30

    Vue style里面使用@import引入外部css, 作用全局解决方案

    问题描述 使用@import引入外部css,作用却是全局 export default { name...background-color: #3982e5; } Add “scoped” attribute to limit CSS to this component only 这句话大家应该是见多了, 我也使用...scoped, 但是使用@import引入外部样式表作用依然是全局,看了一遍@import规则后, 进行初步猜测,难道是@import引入外部样式表错过了scoped style?...又回想到此前看过前端性能优化文章里面都有提到,在生产环境不要使用@import引入css,因为在请求到css中含有@import引入css的话,会发起请求把@importcss引进来,多次请求浪费不必要资源.../static/css/user.css"; 我们只需把@import改成引入外部样式,就可以解决样式是全局问题 <style scoped

    1.4K30

    Laravel Eloquent 模型关联关系(下)

    在前面两篇教程,学院君陆续给大家介绍了 Eloquent 模型类支持七种关联关系,通过底层提供关联方法,我们可以快速实现模型间关联,并且进行关联查询。...另外,如果访问是模型实例上 author() 方法时,返回不是用户实例了,而是一个关联关系实例,该实例注入了查询构建器,所以你可以在其基础上通过方法链方式构建查询构建器进行更加复杂查询,我们一个一对多查询为例...whereHas/orWhereHas 方法基于闭包函数定义查询条件,比如我们想要过滤发布文章标题中包含「Laravel学院」所有用户: $users = User::whereHas('posts...: 如果你想进一步过滤出文章标题和评论都包含「Laravel学院」用户,可以在上述闭包函数通过查询构建器进一步指定: $users = User::whereHas('posts', function...whereHas 方法和 orWhereHas 方法相对,也有 whereDoesntHave 和 orWhereDoesntHave 方法,使用方法一样,这里就不再赘述了。

    19.6K30

    Laravel关联模型过滤结果为空结果集(has和with区别)

    数据结构是三张表用户优惠券表(user_coupons)、优惠券表(coupons),商家表(corps),组优惠券表(group_coupons) (为了方便查看,后两项已去除) 这里我本意想用模型关联查出用户优惠券属于给定组...后来看到了Laravel关联模型has()方法,has()是基于存在关联查询,下面我们用whereHas()(一样作用,只是更高级,方便写条件) 这里我们思想是把判断有没有优惠券数据也放在第一次查询逻辑...加上whereHas()后代码如下 $userCoupons = UserCoupons::whereHas('coupon', function($query) use($groupId){ return...然后走下一步with()查询,因为此时都筛选一遍了,所以with可以去掉条件。 显然区分这两个作用很重要,尤其是在列表,不用特意去筛选为空数据,而且好做分页。...总结 以上所述是小编给大家介绍Laravel关联模型过滤结果为空结果集(has和with区别),希望对大家有所帮助,如果大家有任何疑问请给我留言,小编会及时回复大家

    3.4K40

    laravel ORM关联关系 with和whereHas用法

    with 渴求式预加载 可以有效避免 N+1 问题,用法如下: $books = App\Book::with('author')- get(); 如果有多个关联关系可以用“,”隔开,还可以使用闭包来对关联关系进行限制...),没有筛选功能 with 更像 sql join,就是你存不存都有执行,存在结果不为空,存在关联结果,不存在结果为空,关联结果为空 whereHas 查询存在关联关系,还有对应 whereDoesntHave...,查询不存在关联关系,像下面这样: // 获取发布文章标题中有first用户 $users= User::whereHas('posts', function ($query) { $query...,适合查找 存在不存在 感觉 with 更多用在查看详情时候,你想知道你查看对象具体信息,关联到内容是怎样, 而 whereHas 更多用在筛选,你要把符合条件关联关系对象给他找出来。...这就是我对 with 和 whereHas 一些理解了 以上这篇laravel ORM关联关系 with和whereHas用法就是小编分享给大家全部内容了,希望能给大家一个参考。

    4K31

    Laravel学习记录--Model

    Laravel 自带 软删除功能 就利用全局作用从数据库中提取「未删除」模型。编写自定义全局作用可以提供一个方便、简单方法来确保给定模型每个查询都受到一定约束。...要将全局作用分配给模型,需要重写给定模型 boot 方法并使用 addGlobalScope 方法: <?...删除全局作用 删除一个全局作用 User::withoutGlobalScope(AgeScope::class)->get(); 删除多个全局作用 如果你想要删除几个甚至全部全局作用,可以使用...LaravelEloquent还支持动态作用,动态作用指在查询过程动态设置预置过滤器查询条件,动态作用与本地作用类似,都是以scope作为前缀,调用方法也相同,不同是动态作用可以通过额外参数指定查询条件...','>',$price) } 在查询时直接调用 $goods = Good::Price(200)->get(); 全局作用可理解为限制约束,本地作用/动态作用则可理解为一些定义好常用约束集合

    13.6K20

    3分钟短文:Laravel模型作用,为你“节省”更多代码

    全局作用 假设有些数据库查询操作,无论是在控制器内,或者在模板文件内,或者命令行方法内,都有重复使用需求,要是在模型内有一个公用方法,默认就加上这些筛选条件,就可以显著减少代码量了。...events WHERE `published` = 1; 如果条件 published = 1 在默认情况下需要开启,我们可以使用laravel模型 全局作用 方式为所有查询追加上这个条件。...本地作用 接上一节 withoutGlobalScope 要每次手动屏蔽方式不同,有时候使用有局限作用更能解决问题。...使用使用,直接传入: $zip = '43016'; $events = Event::zip($zip)->get(); 这样就完成了本地作用使用,是不是很直观。...讲述了两个方法: 全局作用全局作用,需要手动移除; 本地作用:只有手动调用起作用,可链式使用; 这样设计模式可以很大程度上节约查询代码,但是对于维护,需要同等熟悉开发者彼此遵循开发规范,写出可维护代码

    1.4K22

    3分钟短文 | Laravel复杂SQL超多WHERE子句,本地作用你没用过

    就拿这个 model 查询说起,你可以 "查询作用”这么个时髦功能,有效分散和重用查询条件。 拿“全局作用”来说,它可以给模型查询都添加上约束。...Laravel 软删除功能就是利用此特性从数据库获取 “未删除”模型。 你可以编写你自己全局作用,很简单、方便为每个模型查询都加上约束条件。看官方给出示例: ?...要将全局作用分配给模型,需要重写模型 booted 方法并使用 addGlobalScope 方法: ?...SQL 学习了全局作用,那么本地作用就更好理解了。...就是在对应 Eloquent 模型方法前添加 scope 前缀,在模型构造如下作用方法: ?

    2.8K10

    3分钟短文:Laravel 从软删除说到模型作用概念

    我们从软删除使用,再顺便说一说模型内作用概念。 代码时间 常规删除操作分两步进行,一步是把数据从数据库查询出来,使用laravel模型方法, 则返回是一个模型对象。...然后在模型,引入软删除功能,将其进行全局生效使用。...格式} 通过追寻源代码,我们注意到 SoftDeletes 其实是注册了一个模型内全局作用方法: public static function bootSoftDeletes(){ static...如果是想软删除条目那样,默认把所有的查询都追加 自定义查询条件,就需要我们上面说全局作用了。...写在最后 本文从laravel模型写操作删除动作,讲到了软删除概念。进而引申出来本地作用全局作用使用。软删除几乎贯穿了我们应用始终,需要大家勤学苦练。

    1.4K30

    【半译】在ASP.NET Core创建内部使用作用服务Quartz.NET宿主服务

    在我上一篇文章,我展示了如何使用ASP.NET Core创建Quartz.NET托管服务并使用它来按计划运行后台任务。...作业可以直接使用作用服务 由于作业实例是从IServiceProvder作用域中解析来,因此您可以在作业实现构造函数安全地使用作用服务。...可替代解决方案 我喜欢本文中显示方法(使用中间QuartzJobRunner类),主要有两个原因: 您其他IJob实现不需要任何有关创建作用基础结构知识,只需完成标准构造函数注入即可 在IJobFactory...该QuartzJobRunner通过创建和处理作用隐式地处理这个问题。 但是,此处显示方法并不是在工作中使用范围服务唯一方法。...该运行程序负责创建一个DI范围,实例化请求作业并执行它,因此最终IJob实现可以在其构造函数中使用作用域中服务。

    1.8K10

    Laravel5.7 Eloquent ORM快速入门详解

    Laravel 自带软删除功能就使用全局作用来从数据库拉出所有没有被删除模型。编写自定义全局作用可以提供一种方便、简单方式来确保给定模型每个查询都有特定条件约束。...应用全局作用 要将全局作用应用到模型,需要重写给定模型 boot 方法并使用 addGlobalScope 方法: <?...,如果使用 User::all() 查询则会生成如下 SQL 语句: select * from `users` where `age` 200 匿名全局作用 Eloquent 还允许我们使用闭包定义全局作用...如果想要在给定查询移除指定全局作用,可以使用 withoutGlobalScope 方法,该方法接收全局作用类名作为其唯一参数: User::withoutGlobalScope(AgeScope...::class)- get(); 或者,如果你使用闭包定义全局作用的话: User::withoutGlobalScope('age')- get(); 如果你想要移除某几个或全部全局作用,可以使用

    15.1K41

    CentOS7.6 为基础镜像 Docker 容器通过 NFS 将内存挂载成高速硬盘使用

    CentOS7.6 为基础镜像 Docker 容器通过 NFS 将内存挂载成高速硬盘使用 文章目录 在 CentOS7.6 为基础镜像 Docker 容器通过 NFS 将内存挂载成高速硬盘使用...通过对问题分析,我采取了以下解决方案: 通过把内存挂载成硬盘,可以大幅度提高磁盘性能; 由于不能在同一个容器内进行读写,可以使用 NFS 来解决; 允许使用特权模式,可以在容器内部挂载磁盘...适用范围狭窄; 不能通过 systemd 来管理服务; 生产环境不推荐使用此方案。...4.2.2 Docker 容器互联 在同一台主机未指定网络方案情况下,Docker 是通过 bridge 方式进行桥接。如果涉及到跨主机互联,那么可能需要使用其他方案。...4.2.3 在容器其他 NFS 解决方案 nfs-ganesha 也是 NFS 在容器一个比较流行解决方案。

    2.2K30

    Laravel Eloquent 模型类中使用作用进行查询

    User 模型类为例,我们在系统可能只想针对已经验证过邮箱用户进行操作,在没有介绍「作用」之前,可能你会在应用到处编写这样代码: $users = User::whereNotNull('...这样,当我们通过 User 模型类进行查询时候,就会自动应用全局作用指定查询条件了, User::all() 为例,我们通过 Telescope 「Queries」 页面就能看到对应 SQL...通过匿名函数实现 如果你觉得编写一个「全局作用」类很麻烦,过滤逻辑又很简单,还可以在模型类 boot 方法通过匿名函数实现全局作用: protected static function boot...,不同场景需要不同预置过滤器,这个时候就不能使用全局作用」了,要改用「局部作用」,在不同场景应用不同局部作用来完成查询功能。...动态作用 此外,Eloquent 模型类还支持「动态作用」,所谓动态作用指的是在查询过程动态设置预置过滤器查询条件,动态作用和局部作用类似,过滤器方法名同样 scope 开头,只不过可以通过额外参数指定查询条件

    2.5K20

    前端关键技术点杂烩,这些你必须知道

    父函数定义变量在子函数作用,子函数没有被销毁,其作用链中所有变量和函数就会被维护,不会被销毁。...20、JS 作用链 在一些类 C 语言中有“块级作用”,即花括号每一段代码都有自己独立作用,而 JS 只有函数级作用;JS 作用第一个对象始终是当前执行代码所在环境变量对象(VO)...,声明函数在全局作用,此时作用链只有一个环境对象;运行函数时作用链顶端加入了函数内环境对象,运行完毕时顶端环境对象被销毁,以此类推。...JS 在查找变量时会从链顶端(就近原则)一直向下查找。如果一个跨作用对象被引用了一次以上,则先把它存储到局部变量里再使用。...全局变量总是存在于运行期上下文作用最末端,因此在标识符解析时候,查找全局变量是最慢。 (最好和闭包一起理解) 21、你对前端有什么理解?

    1.6K20
    领券