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

简介: 为代码瘦身

引言
原则上代码写一次,处处是引用,不需要大量的冗余代码,这是一种趋势,也是提高代码健壮性的努力方向。 laravel模型为我们提供了一层数据库操作层,将数据交互独立出来。
但是久而久之,随着项目的需求不断扩大,最常用的查询操作,同样会有大量的冗余代码。

本文就来讲讲,连模型的自我瘦身,缩减模型的代码。
全局作用域
假设有些数据库查询操作,无论是在控制器内,或者在模板文件内,或者命令行方法内,都有重复的使用需求,要是在模型内有一个公用的方法,默认就加上这些筛选条件,就可以显著减少代码量了。
比如有一个查询条件:
$publishedEvents = Event::where('published', '=', 1)->get();
上述代码最后生成的SQL语句如下:
SELECT * FROM events WHERE published = 1;
如果条件 published = 1 在默认的情况下需要开启,我们可以使用laravel模型的 全局作用域 方式为所有查询追加上这个条件。
在模型文件 Event 内头部引入下述类:
use IlluminateDatabaseEloquentModel;
use IlluminateDatabaseEloquentBuilder;
在模型类内部,手动实现 boot 方法:
protected static function boot()
{

parent::boot();
static::addGlobalScope('published', function (Builder $builder) {
    $builder->where('published', '=', 1);
});

}
这样SQL语句 where published = 1 就会追加到所有的模型查询方法内,只要是创建生成了 QueryBuilder 对象的,都会附加上此约束语句。
那有些读者可能要问了:“如果我不想要这个约束语句,岂不是连模型也永不了了?”
那哪儿能呢!不过就是QueryBuilder的一个属性数组的一个元素而已,手动移除就行了,这样特例问题就解决了。
$events = Event::withoutGlobalScopes()->get();
看到了吧,追加上很简单,移除更简单。

本地作用域
接上一节的 withoutGlobalScope 要每次手动屏蔽的方式不同,有时候使用有局限的作用域更能解决问题。所以,本地作用域 应运而生,专门用于某个模型文件的方法,手动调用的时候就起作用,不调用就不会主动追加。
而声明一个本地作用域,只要遵循laravel的语法规定即可,如下示例:
public function scopePublished($query)
{

return $query->where('published', 1);

}
只需要声明一个以 scope 为首的小驼峰命名的函数方法即可,并返回一个 QueryBuilder 对象实例。调用的时候要手动追加上:
$events = Event::published()->get();
其中 published()方法就是映射到 scopePublished 方法。
上面的演示代码,没有接收用户输入,下面演示一下带参的传递方式。比如有这样一个查询需求:
$events = Event::where('zip', $zipCode)->get();
使用本地作用域实现出来:
public function scopeZip($query, $zip)
{

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

}
按照位置传入即可。使用的使用,直接传入:
$zip = '43016';
$events = Event::zip($zip)->get();
这样就完成了本地作用域的使用,是不是很直观。
既然本地作用域返回的是 QueryBuilder 实例,那么自然就可以链式调用本地作用域的方法,和 QueryBuilder 的方法。我们再声明一个本地作用域方法:
public function scopeAttendees($query, $maximum)
{

return $query->where('max_attendees', $maximum);

}
现在把上述两个方法串联使用:
$events = Event::zip(43016)->attendees(2)->get();
生成的SQL语句也符合预期:
SELECT * FROM events WHERE zip = '43016' and max_attendees = '2';
写在最后
本期我们又旧事重提,把laravel模型的作用域设计方法拿出来温习了一下。讲述了两个方法:
全局作用域:全局起作用,需要手动移除;
本地作用域:只有手动调用起作用,可链式使用;
这样的设计模式可以很大程度上节约查询代码,但是对于维护,需要同等熟悉的开发者彼此遵循开发规范,写出可维护的代码。

Happy coding :-)

我是@程序员小助手,专注编程知识,圈子动态的IT领域原创作者

相关文章
|
9月前
|
设计模式 算法 前端开发
有什么可以减少注释,但依然能让他人看得懂代码的方法吗?
有什么可以减少注释,但依然能让他人看得懂代码的方法吗?
70 0
|
7月前
|
监控 测试技术 Python
颠覆传统!Python闭包与装饰器的高级实战技巧,让你的项目效率翻倍
【7月更文挑战第7天】Python的闭包与装饰器是强大的工具。闭包是能记住外部作用域变量的内部函数,常用于动态函数创建和工厂模式。例如,`make_power`返回含外部变量`n`的`power`闭包。装饰器则允许在不修改函数代码的情况下添加新功能,如日志或性能监控。`my_decorator`函数接收一个函数并返回包装后的函数,添加了前后处理逻辑。掌握这两者,可提升编程效率和灵活性。
55 3
|
4月前
|
JSON 计算机视觉 数据格式
LangChain-17 FunctionCalling 利用大模型对函数进行回调 扩展大模型的额外的能力 比如实现加减乘除等功能
LangChain-17 FunctionCalling 利用大模型对函数进行回调 扩展大模型的额外的能力 比如实现加减乘除等功能
92 4
|
6月前
|
前端开发 测试技术 UED
React性能优化的神奇之处:如何用懒加载与代码分割让你的项目一鸣惊人?
【8月更文挑战第31天】在现代Web开发中,性能优化至关重要。本文探讨了React中的懒加载与代码分割技术,通过示例展示了如何在实际项目中应用这些技术。懒加载能够延迟加载组件,提高页面加载速度;代码分割则将应用程序代码分割成多个块,按需加载。两者结合使用,可以显著提升用户体验。遵循合理使用懒加载、编写测试及关注性能等最佳实践,能够更高效地进行性能优化,提升应用程序的整体表现。随着React生态的发展,懒加载与代码分割技术将在未来Web开发中发挥更大作用。
71 0
|
7月前
|
Python
告别代码冗余!Python闭包与装饰器如何让你秒变代码优化大师?
【7月更文挑战第6天】Python的闭包和装饰器是解决代码冗余的利器。闭包,如匿名函数,记忆外部作用域变量,实现代码封装。例如,`make_multiplier_of`生成特定乘法函数,避免重复。装饰器如`@my_decorator`,不修改原函数,添加额外功能,如在函数调用前后打印信息。两者结合,提升代码灵活性和复用性,是优化和整洁代码的关键。
46 0
JavaScript_进一步了解字符串拼接~记忆小窍门
JavaScript_进一步了解字符串拼接~记忆小窍门
|
机器学习/深度学习 算法 语音技术
llama.cpp作者创业,用纯C语言框架降低大模型运行成本
llama.cpp作者创业,用纯C语言框架降低大模型运行成本
925 0
|
存储 编译器 文件存储
C++语言中多文件组合方式之经典
C++语言中多文件组合方式之经典
251 0
|
缓存
GoogleGuava - 第 3 章 缓存——范例 & 适用性
GoogleGuava - 第 3 章 缓存——范例 & 适用性
104 0
GoogleGuava - 第 3 章 缓存——范例 & 适用性