312篇
一、除了检索与给定查询匹配的所有记录之外,您还可以使用 find、first 或 firstWhere 方法检索单个记录。 这些方法不返回模型集合,而是返回单个模型实例:
use App\Models\Flight;
// 使用主键检索模型...
$flight = Flight::find(1);
// 检索符合查询条件的第一个模型...
$flight = Flight::where('active', 1)->first();
// 检索匹配查询条件的第一个模型的替代方法...
$flight = Flight::firstWhere('active', 1);
注:firstWhere这个就比较好
有时,您可能希望检索查询的第一个结果或在未找到结果时执行其他操作。 firstOr 方法将返回匹配查询的第一个结果,或者,如果没有找到结果,则执行给定的闭包。 闭包返回的值将被视为 firstOr 方法的结果:
$model = Flight::where('legs', '>', 3)->firstOr(function () {
// ...没找到,做一些返回报错处理
});
firstOr可以少写一个if,很巧妙
二、局部作用域
局部作用域允许定义通用的约束集合以便在应用程序中重复使用。例如,你可能经常需要获取所有「流行」的用户。要定义这样一个范围,只需要在对应的 Eloquent 模型方法前添加 scope 前缀。
作用域总是返回一个查询构造器实例:
<?php
namespace App\Models;
use Illuminate\Database\Eloquent\Model;
class User extends Model
{
/**
* 只查询受欢迎的用户的作用域
*
* @param \Illuminate\Database\Eloquent\Builder $query
* @return \Illuminate\Database\Eloquent\Builder
*/
public function scopePopular($query)
{
return $query->where('votes', '>', 100);
}
/**
* 只查询 active 用户的作用域
*
* @param \Illuminate\Database\Eloquent\Builder $query
* @return \Illuminate\Database\Eloquent\Builder
*/
public function scopeActive($query)
{
return $query->where('active', 1);
}
}
使用局部作用域
一旦定义了作用域,就可以在查询该模型时调用作用域方法。不过,在调用这些方法时不必包含 scope 前缀。甚至可以链式调用多个作用域,例如:
use App\Models\User;
$users = User::popular()->active()->orderBy('created_at')->get();
通过 or 查询运算符组合多个 Eloquent 模型作用域可能需要使用闭包来实现正确的 逻辑分组:
$users = User::popular()->orWhere(function (Builder $query) {
$query->active();
})->get();
然而这可能有点麻烦,所以 Laravel 提供了一个更高阶的 orWhere 方法,允许你流畅地将作用域链接在一起,而无需使用闭包:
$users = App\Models\User::popular()->orWhere->active()->get();
三、通过静态方法监听模型事件
通过在模型类上调用要监听事件对应的静态方法,一般我们会在某个服务提供者的 boot 方法中完成这项工作,比如 EventServiceProvider。举个例子,假设我们要监听每次获取模型实例的事件并在日志中记录查询到的用户信息,可以这么做:
// app/Providers/EventServiceProvider.php
public function boot()
{
parent::boot();
// 监听模型获取事件
User::retrieved(function ($user) {
Log::info('从模型中获取用户[' . $user->id . ']:' . $user->name);
});
}
上面这段代码中表示我们在 User 模型上监听 retrieved 事件,然后通过一个闭包函数执行对应的处理逻辑,该闭包函数传入参数是模型实例,在处理逻辑中,我们通过 Log 门面记录日志信息。
retrieved, #获取到模型实例后触发
creating, #创建过程前 * 常用
created, #创建成功后 * 常用
updating, #更新过程前 * 常用
updated, #更新成功后 * 常用
saving, #代表这两个方法的集合creating,updating * 常用
saved, #代表这两个方法的集合created,updated * 常用
deleting, #删除过程前 * 常用
deleted, #删除过程后 * 常用
restoring, #恢复软删除记录前触发
restored, #恢复软删除记录后触发
更多创建模型事件的方法请参考https://www.cnblogs.com/jxl1996/p/10339563.html