Eloquent 集合
Eloquent:集合
简介
所有返回多个模型结果的 Eloquent 方法都会返回 Illuminate\Database\Eloquent\Collection 实例,包括通过 get 方法检索或通过关联访问的结果。Eloquent 集合继承自 Laravel 的基础集合,因此也拥有数十个方法,可用于流畅地操作底层的 Eloquent 模型数组。请参阅 Laravel 集合文档,了解这些实用方法。
所有集合也都可以作为迭代器使用,让你像遍历普通 PHP 数组一样遍历集合:
use App\Models\User;
$users = User::where('active', 1)->get();
foreach ($users as $user) {
echo $user->name;
}
不过,集合比数组更强大,提供了多种映射(map)和归约(reduce)操作,并支持直观的链式调用。例如,可以先排除所有未激活的模型,再收集其余用户的名字:
$names = User::all()->reject(function (User $user) {
return $user->active === false;
})->map(function (User $user) {
return $user->name;
});
Eloquent 集合转换
大多数 Eloquent 集合方法会返回新的 Eloquent 集合实例,但 collapse、flatten、flip、keys、pluck 和 zip 返回的是基础集合实例。同样,如果 map 操作返回的集合不包含任何 Eloquent 模型,该集合也会转换为基础集合实例。
可用方法
所有 Eloquent 集合都继承自基础的 Laravel 集合,因此拥有基础集合类提供的全部方法。
此外,Illuminate\Database\Eloquent\Collection 还提供了额外的方法,方便管理模型集合。大多数方法返回 Illuminate\Database\Eloquent\Collection 实例,但 pluck 等方法返回的是 Illuminate\Support\Collection 实例。
append
contains
diff
except
find
findOrFail
fresh
intersect
load
loadMissing
modelKeys
makeVisible
makeHidden
mergeVisible
mergeHidden
only
partition
setAppends
setVisible
setHidden
toQuery
unique
withoutAppends
append($attributes)
append 方法用于为集合中的每个模型设置需要追加的属性,接受属性数组或单个属性:
$users->append('team');
$users->append(['team', 'is_admin']);
contains($key, $operator = null, $value = null)
contains 方法用于判断集合是否包含指定的模型实例,接受主键或模型实例:
$users->contains(1);
$users->contains(User::find(1));
diff($items)
diff 方法返回当前集合中未出现在给定集合中的所有模型:
use App\Models\User;
$users = $users->diff(User::whereIn('id', [1, 2, 3])->get());
except($keys)
except 方法返回主键不在给定列表中的所有模型:
$users = $users->except([1, 2, 3]);
find($key)
find 方法返回主键与给定键匹配的模型。如果 $key 是模型实例,find 会尝试返回与该实例主键匹配的模型;如果 $key 是键数组,则返回主键在该数组中的所有模型:
$users = User::all();
$user = $users->find(1);
findOrFail($key)
findOrFail 方法返回主键与给定键匹配的模型。如果集合中没有匹配的模型,则抛出 Illuminate\Database\Eloquent\ModelNotFoundException 异常:
$users = User::all();
$user = $users->findOrFail(1);
fresh($with = [])
fresh 方法从数据库中重新检索集合中每个模型的新实例,并预加载指定的关联:
$users = $users->fresh();
$users = $users->fresh('comments');
intersect($items)
intersect 方法返回当前集合与给定集合中都存在的所有模型:
use App\Models\User;
$users = $users->intersect(User::whereIn('id', [1, 2, 3])->get());
load($relations)
load 方法为集合中的所有模型预加载指定的关联:
$users->load(['comments', 'posts']);
$users->load('comments.author');
$users->load(['comments', 'posts' => fn ($query) => $query->where('active', 1)]);
loadMissing($relations)
loadMissing 方法为集合中的所有模型预加载指定的关联,但只加载尚未加载的关联:
$users->loadMissing(['comments', 'posts']);
$users->loadMissing('comments.author');
$users->loadMissing(['comments', 'posts' => fn ($query) => $query->where('active', 1)]);
modelKeys()
modelKeys 方法返回集合中所有模型的主键:
$users->modelKeys();
// [1, 2, 3, 4, 5]
makeVisible($attributes)
makeVisible 方法将集合中每个模型通常「隐藏」的属性设为可见:
$users = $users->makeVisible(['address', 'phone_number']);
makeHidden($attributes)
makeHidden 方法将集合中每个模型通常「可见」的属性隐藏:
$users = $users->makeHidden(['address', 'phone_number']);
mergeVisible($attributes)
mergeVisible 方法保留现有的可见属性,并将额外的属性设为可见:
$users = $users->mergeVisible(['middle_name']);
mergeHidden($attributes)
mergeHidden 方法保留现有的隐藏属性,并隐藏额外的属性:
$users = $users->mergeHidden(['last_login_at']);
only($keys)
only 方法返回主键在给定列表中的所有模型:
$users = $users->only([1, 2, 3]);
partition
partition 方法返回一个 Illuminate\Support\Collection 实例,其中包含 Illuminate\Database\Eloquent\Collection 集合实例:
$partition = $users->partition(fn ($user) => $user->age > 18);
dump($partition::class); // Illuminate\Support\Collection
dump($partition[0]::class); // Illuminate\Database\Eloquent\Collection
dump($partition[1]::class); // Illuminate\Database\Eloquent\Collection
setAppends($attributes)
setAppends 方法临时覆盖集合中每个模型的全部追加属性:
$users = $users->setAppends(['is_admin']);
setVisible($attributes)
setVisible 方法临时覆盖集合中每个模型的全部可见属性:
$users = $users->setVisible(['id', 'name']);
setHidden($attributes)
setHidden 方法临时覆盖集合中每个模型的全部隐藏属性:
$users = $users->setHidden(['email', 'password', 'remember_token']);
toQuery()
toQuery 方法返回一个 Eloquent 查询构造器实例,其中包含针对集合中模型主键的 whereIn 约束:
use App\Models\User;
$users = User::where('status', 'VIP')->get();
$users->toQuery()->update([
'status' => 'Administrator',
]);
unique($key = null, $strict = false)
unique 方法返回集合中不重复的模型,主键与其他模型相同的重复模型会被移除:
$users = $users->unique();
withoutAppends()
withoutAppends 方法临时移除集合中每个模型的全部追加属性:
$users = $users->withoutAppends();
自定义集合
要在操作某个模型时使用自定义的 Collection 对象,可以在模型上添加 CollectedBy 特性:
<?php
namespace App\Models;
use App\Support\UserCollection;
use Illuminate\Database\Eloquent\Attributes\CollectedBy;
use Illuminate\Database\Eloquent\Model;
#[CollectedBy(UserCollection::class)]
class User extends Model
{
// ...
}
也可以在模型中定义 newCollection 方法:
<?php
namespace App\Models;
use App\Support\UserCollection;
use Illuminate\Database\Eloquent\Collection;
use Illuminate\Database\Eloquent\Model;
class User extends Model
{
/**
* 创建一个新的 Eloquent 集合实例。
*
* @param array<int, \Illuminate\Database\Eloquent\Model> $models
* @return \Illuminate\Database\Eloquent\Collection<int, \Illuminate\Database\Eloquent\Model>
*/
public function newCollection(array $models = []): Collection
{
$collection = new UserCollection($models);
if (Model::isAutomaticallyEagerLoadingRelationships()) {
$collection->withRelationshipAutoloading();
}
return $collection;
}
}
定义 newCollection 方法或在模型上添加 CollectedBy 特性后,Eloquent 原本会返回 Illuminate\Database\Eloquent\Collection 实例的地方,都会返回自定义集合实例。
如果希望应用中的所有模型都使用自定义集合,可以在基础模型类中定义 newCollection 方法,再让应用中的所有模型继承该类。
本译文仅用于学习和交流目的,转载请务必注明文章译者、出处、和本文链接
我们的翻译工作遵照 CC 协议,如果我们的工作有侵犯到您的权益,请及时联系我们。
Laravel 13 中文文档
关于 LearnKu
推荐文章: