数据库模型与 Eloquent
复用或克隆 query
通常,我们需要从过滤后的查询中进行更多次查询。因此,大多数时候我们使用 query() 方法, 让我们编写一个查询来获取今天创建的可用和不可用的产品
$query = Product::query();
$today = request()->q_date ?? today();
if($today){
$query->where('created_at', $today);
}
// 让我们获取可用和不可用的产品
$active_products = $query->where('status', 1)->get(); // 这一行 修改了$query 对象变量
$inactive_products = $query->where('status', 0)->get(); // 所以这里我们将获取不到任何不可用产品但是,在获得 $active products 后,$query 会被修改。因此 $inactive_products 不会从 $query 中获取到不可用产品,并且每次都返回空集合。因为,它尝试从 $active_products 中查找不可用产品($query 仅返回可用产品)。
为了解决这个问题,我们可以通过重用这个$query对象来查询多次。因此我们在做任何对$query修改操作的时候需要克隆这个$query。
$active_products = $query->clone()->where('status', 1)->get(); // it will not modify the $query
$inactive_products = $query->clone()->where('status', 0)->get(); // so we will get inactive products from $queryEloquent where 日期方法
在 Eloquent 中,使用 whereDay()、whereMonth()、whereYear()、whereDate() 和 whereTime() 函数检查日期。
增量和减量
如果要增加数据库某个表中的某个列的值,只需要使用 increment() 函数。你不仅可以增加 1,还可以增加其他数字,如 50。
禁止 timestamp 列
如果你的数据库表不包含 timestamp 字段 created_at 和 updated_at,你可以使用 $timestamps = false 属性指定 Eloquent 模型不使用它们。
软删除-多行恢复
使用软删除时,可以在一个句子中恢复多行。
Model all-columns
当调用Eloquent's Model::all()时你可以指定返回哪些列。
To Fail or not to Fail
除了 findOrFail() 之外,还有 Eloquent 方法 firstOrFail(),如果没有找到查询记录,它将返回 404 页面。
列名修改
在 Eloquent Query Builder 中,您可以像在普通 SQL 查询中一样指定as以返回任何列的别名。
过滤结果集合
在 Eloquent 查询到结果之后,您可以使用 Collections 中的 map() 函数来修改行数据。
修改默认的 Timestamp 字段
如果您使用的是非 Laravel 数据库并且时间戳列的名称不同怎么办?也许,你有 create_time 和 update_time。 幸运的是,您也可以在模型中指定它们:
按照 created_at 快速排序
不用:
你可以更快的使用排序:
默认情况下 latest() 将按照 created_at排序。
有一个相反的方法 oldest(),按 created_at 升序排序:
您也可以指定另一列进行排序。 例如,如果你想使用 updated_at,你可以这样做:
当创建记录时自动修改某些列的值
如果您想在创建记录时生成一些 DB 列值,请将其添加到模型的 boot() 方法中。 例如,如果您有一个字段 「position」,并且想要赋值下一个可用位置(如 Country::max('position') + 1),请执行以下操作:
数据库原始查询计算运行得更快
使用类似 whereRaw() 方法的 SQL 原始查询,直接在查询中进行一些数据库特定计算,而不是在 Laravel 中,通常情况下结果会更快。 例如,如果您想获得注册后 30 天以上仍处于活跃状态的用户,代码如下:
不止一个范围
您可以在 Eloquent 中组合和链式调用查询范围,在一个 query 查询中使用多个范围。
Model文件内:
控制器内:
无需转换 Carbon
如果你正使用 whereDate() 查询今日的记录,可以直接使用 Carbon 的 now() 方法,它会自动转换为日期进行查询,而不需要指定 ->toDateString()。
根据首字母分组
你可以用任意自定义条件对 Eloquent 结果进行分组,下面的示例是由用户名的第一个单词进行分组:
永不更新某个字段
如果有一个数据库字段你想只设置一次并不想再次更新,您可以在Eloquent的模型上使用一个修改器设置该限制:
find 查询多条数据
find() 方法可以接受多参数, 传入多个值时会返回所有找到记录的集合,而不是一个模型:
由 @tahiriqbalnajam 提供
find 多个模型并返回多列
find 方法可接受多参数 使得结果集返回指定列的模型集合,而不是模型的所有列:
由 @tahiriqbalnajam 提供
按照键查找
您还可以使用 whereKey() 方法根据您指定的主键查找多条记录。(默认 id 但是你可以在 Eloquent 模型中覆盖掉)
使用 UUID 替换 auto-increment
您不想在模型中使用自动递增 ID?
迁移:
模型:
Laravel 中的子查询
从 Laravel 6 开始,您可以在 Eloquent 语句中使用 addSelect()方法,对列进行一些计算。
隐藏某些列
在进行 Eloquent 查询时,如果您想在返回中隐藏特定字段,最快捷的方法之一是在集合结果上添加 ->makeHidden()。
确定 DB 报错
如果您想捕获 Eloquent Query 异常,请使用特定的 QueryException 代替默认的 Exception 类,您将能够获得SQL确切的错误代码。
软删除与查询构造器
注意 当你用到 Eloquent 时 软删除将会起作用,但是查询构造器不行。
SQL 声明
如果你需要执行一个简单的 SQL 查询,但没有方案 —— 比如改变数据库模式中的某些东西,只需执行 DB::statement()。
数据库事务
如果您执行了两个数据库操作,第二个可能会出错,那么您应该回滚第一个,对吗? 为此,我建议使用 DB Transactions,它在 Laravel 中非常简单:
更新或创建
如果你需要检查记录是否存在,然后更新它,或者创建一个新记录,你可以用一句话来完成 - 使用 Eloquent updateOrCreate() 方法:
保存时移除缓存
如果您缓存了一个键存储了 posts 这个集合,想在新增或更新时移除缓存键,可以在您的模型上调用静态的 saved 函数:
由 @pratiksh404 提供
修改 Created_at 和 Updated_at 的格式
想要改变 created_at 的格式,您可以在模型中添加一个方法,如下所示:
你可以在需要改变时间格式时使用 $entry->created_at_formatted ,它会返回 created_at 的属性如同 04:19 23, Aug 2020。
你也可以用同样的方法更改 updated_at:
在有需要的时候使用 $entry->updated_at_formatted。它会返回 updated_at 的属性如同: 04:19 23, Aug 2020 。
由 @syofyanzuhad 提供
数组类型存储到 JSON 中
如果你的输入字段有一个数组需要存储为 JSON 格式,你可以在模型中使用 $casts 属性。 这里的 images 是 JSON 属性
这样你可以以 JSON 格式存储它,但当你从 DB 中读取时,它会以数组方式使用。
由 @pratiksh404 提供
复制一个模型
如果你有两个非常相似的模型(比如送货地址和账单地址),而且你想要复制其中一个作为另一个,你可以使用 replicate() 方法并更改一部分属性。
降低内存占用
有时我们需要将大量的数据加载到内存中,比如:
但如果我们有非常庞大的数据库,这可能会很慢,因为 Laravel 会准备好模型类的对象。在这种情况下,Laravel 有一个很方便的函数 toBase()。
通过调用这个方法,它将从数据库中获取数据,但它不会准备模型类。同时,向 get() 方法传递一个字段数组通常是个好主意,这样可以防止从数据库中获取所有字段。
忽略 $fillable / $guarded 并强制执行
如果你为其他开发者创建了一个 Laravel 模板, 然后你不能控制他们以后会在模型的 $fillable / $guarded 中填写什么,你可以使用 forceFill()
如果 name 不在team模型的 $fillable 中,怎么办?或者如果根本就没有 $fillable/$guarded, 怎么办?
这将忽略该查询的 $fillable 并强制执行。
3 层父子级结构
If you have a 3-level structure of parent-children, like categories in an e-shop, and you want to show the number of products on the third level, you can use with('yyy.yyy') and then add withCount() as a condition
使用 find 来搜索更多的记录
你不仅可以用 find() 来搜索单条记录,还可以用 IDs 的集合来搜索更多的记录,方法如下:
这么做:
如果是整数使用 "whereIntegerInRaw" 比 "whereIn "快。
由 @sachinkiranti 提供
失败时执行任何操作
当查询一条记录时,如果没有找到,你可能想执行一些操作。除了用 ->firstOrFail() 会抛出 404 之外,你可以在失败时执行任何操作,只需要使用
->firstOr(function() { ... })
检查记录是否存在否则显示 404
不要使用 find() ,然后再检查记录是否存在,使用 findOrFail()
更简单的方法:
条件语句为否时中止
可以使用 abort_if() 作为判断条件和抛出错误页面的快捷方式。
更简单的方法:
在删除模型之前执行任何额外的操作
我们可以使用 Model::delete() 执行额外的操作来覆盖原本的删除方法
由@back2Lobby 提供
当你需要在保存数据到数据库时自动填充一个字段
当你需要在保存数据到数据库时自动填充一个字段 (例如: slug),使用模型观察者来代替重复编写代码
由 @sky_0xs 提供
获取查询语句的额外信息
你可以使用 explain() 方法来获取查询语句的额外信息
由 @amit_merchant 提供
在 Laravel 中使用 doesntExist() 方法
由 @ShawnHooper 提供
在一些模型的 boot () 方法中自动调用一个特性
如果你有一个特性,你想把它添加到几个模型中,自动调用它们的 boot() 方法,你可以把特性的方法作为 boot (特性名称)来调用
Laravel 的 find 方法,比只传一个 ID 更多的选择
在 Laravel 中有两种常见的方法来确定一个表是否为空表
在 Laravel 中,有两种常见的方法来确定一个表是否为空表。 直接在模型上使用 exists() 或者 count() 不等于一个返回严格的布尔值,另一个返回一个整数,你都可以在条件语句中使用。
由 @aschmelyun 提供
如何避免 property of non-object 错误
由 @coderahuljat 提供
Eloquent 数据改变后获取原始数据
Eloquent 模型数据改变后,你可以使用 getOriginal () 方法来获取原始数据
由 @devThaer 提供
一种更简单创建数据库的方法
Laravel 还可以使用 .sql 文件来更简单的创建数据库
由 @w3Nicolas 提供
Query构造器的crossJoinSub方法
使用CROSS JOIN交叉连接
由 @PascalBaljet 提供
belongsToMany 的中间表命名
为了决定 关系表的中间表, Eloquent 将按字母顺序连接两个相关的型号名称。
这意味着可以这样添加 “Post” 和 “Tag” 之间的连接:
但是,您可以自由重写此约定,并且需要在第二个参数中指定联接表。
如果希望明确说明主键,还可以将其作为第三个和第四个参数提供。
由 @iammikek 提供
根据 Pivot 字段排序
BelongsToMany::orderByPivot() 允许你直接对BelongsToMany 关系查询的结果集进行排序。
由 @PascalBaljet 提供
从数据库中查询一条记录
sole() 方法将会只返回一条匹配标准的记录。如果没找到,将会抛出NoRecordsFoundException 异常。如果发现了多条记录,抛出MultipleRecordsFoundException 异常
由 @PascalBaljet 提供
记录自动分块
与 each() 相同,但是更简单使用。chunks 自动将记录分成多块。
由@PascalBaljet 提供
定时清理过期记录中的模型
定期清理过时记录的模型。有了这个特性,Laravel 将自动完成这项工作,只需调整内核类中 model:prune 命令的频率
此外,在修剪方法中,可以设置删除模型之前必须执行的操作:
由 @PascalBaljet 提供
不变的日期和对它们的强制转换
Laravel 8.53 介绍了 immutable_date 和immutable_datetime 将日期转换为 Immutable.
转换成 CarbonImmutable,而不是常规的 Carbon 实例。
由 @PascalBaljet 提供
findorfail方法也接收ids数组
findorfail 方法也接收 ids 数组。若无 ids 被找到 则失败。
若你想拿到一个模型的集合 并不想检测返回数量为你想得到的数量时很好用。
由 @timacdonald87 提供
从你的数据库中自动移除模型 prunableTrait
Laravel 8.50新特性:
你可以使用 prunable trait 从你的数据库中自动移除模型。举例:你可以在几天后永久移除软删除的模型。
由 @Philo01 提供
日期转换
当标记改变时 原来用布尔值来控制模型的可见性,现在可以使用something_at 替换。比如 一个产品变成可见:
由 @alexjgarrett 提供
多模型更新插入
upsert() 方法将插入/更新多个记录。
第一个参数数组:要更新/插入的值
第二个:查询表达式中使用的唯一标识列
第三个:若记录存在 你想要更新的列
由 @mmartin_joo 提供
过滤结果集之后获取查询构造器
你可以使用 toQuery() 在过滤结果集之后获取查询构造器。
该方法在内部使用集合的第一个模型 并使用集合模型上的 “whereKey” 比较器。(此处翻译拗口 存疑。但是使用方法很明确。)
由 @RBilloir 提供
选择聚合计算相关模型
选择聚合计算相关模型。
需要指出的是在一组相关模型上使用 count 方法要慢一点。
由 @alexjgarrett 提供
自定义强制转换
你可以自定义强制转换来让 Laravel 自动格式化你的模型数据。
下面是一个在检索或更改用户名时将其大写的示例。
由 @mattkingshott 提供
保存中不要触发事件
若你不想触发模型事件 使用 saveQuietly() 方法
由 @mmartin_joo 提供
基于相关模型的平均值或总数排序
你是否曾需要基于关系模型的平均值或总数来排序?
这很简单
由 @mmartin_joo 提供
返回事务结果
若你有一个 DB 事务 并且你想返回它的结果 至少有两种方法:
从 query 中移除多个公共 scope
当使用 Global Scopes 时 你不仅可以使用多个 scope 而且可以在不需要的时候通过提供的 withoutGlobalScopes 方法移除他们
JSON 列属性排序
你可以使用 JSON 列属性排序
由 @brbcoding 提供
从第一个结果中获取单列的值
你可以使用 value 方法从第一个结果中获取单列的值。
由 @justsanjit 提供
检测模型属性是否被修改
想知道您对模型所做的更改是否改变了键的值吗?没问题,只需originalIsEquivalent 方法即可。
由 @mattkingshott 提供
定义访问器与修改器的新方法
Laravel 8.77:定义访问器与修改器的新方法
由 @Teacoders 提供
另外一种定义访问器与修改器的方法
在一些模型中想用同样的修改器 访问器 可以自定义转换。
只需要创建一个类 实现 CastsAttributes 实现两个方法
get 标识模型应当从数据库如何拿到
set 标识数据应当如何存储到数据库
然后你可以在模型中实现这个转换
由 @AhmedRezk 提供
在搜索第一条记录时,你可以执行一些操作
当搜索第一条记录时,你想执行一些操作,当你没有找到它时。 firstOrFail() 抛出一个 404 异常。
你可以用 firstOr(function() {}) 代替。 Laravel帮你解决了这个问题
由 @bhaidar 提供
直接将 created_at 日期转换为人性化格式
你知道吗,你可以使用 diffForHumans() 函数直接将 created_at 日期转换成人性化格式,如 1 分钟前,1 个月前。Laravel eloquent 默认在 created_at 字段上启用 Carbon 实例。
由 @vishal__2931 提供
通过获取器排序
我们不是按数据库级别排序,而是按返回的集合的获取器排序。
sortByDesc 和 sortBy 方法在集合中。
由 @bhaidar 提供
创建或发现特定模型的检查
如果你想检查特定模型是否被创建或找到,使用 wasRecentlyCreated 模型属性。
由 @sky_0xs 提供
带有数据库驱动的 Laravel Scout
使用 laravel v9,你可以使用 Laravel Scout(搜索)与数据库驱动程序。
由 @magarrent 提供
使用查询生成器的 value 方法
当你只需要检索一个列时,利用查询生成器上的 value 方法来执行一个更有效的查询。
由 @mattkingshott 提供
将数组传给 where 方法
你可以传递一个数组给 where 方法。
由 @cosmeescobedo 提供
从模型集合中返回主键
你知道 eloquent 中的 modelsKeys() 集合方法吗?它从模型集合中返回主键。
由 @iamharis010 提供
永久关闭懒加载
如果你想在你的应用程序中阻止懒加载,你只需要在你的 "AppServiceProvider" 的 "boot() " 方法中添加以下一行
但是,如果你想只在你的本地开发中启用这个功能,你可以改变上述代码。
由 @CatS0up 提供
使你所有的模型的字段批量分配
出于安全原因,这不是一个推荐的方法,但它是可能的。
当你想这样做时,你不需要为每个模型设置一个空的 $guarded 数组,像这样:
只要在你的 "AppServiceProvider" 中的 "boot() " 方法中添加以下一行:
现在,你的所有模型都是可以自动分配的。
由 @CatS0up 提供
在查询语句中隐藏列
如果你使用 Laravel v8.78 和 MySQL 8.0.23 及以上版本, 你可以将选择的列定义为 "invisible"。被定义为 "invisible" 的列将被隐藏在 "select *" 语句中。
然而,要做到这一点,我们必须在迁移中使用一个 invisible() 方法。
这将使选择的列从 "select *" 语句中隐藏
由 @CatS0up 提供
最后更新于
这有帮助吗?