简介
laravel 集合 对于处理数据数组来说非常强大。它们提供了一种流畅、便捷的接口,用于执行常见的数组操作,如过滤、格式化和转换数据。在这篇博客文章中,我们将探讨 laravel 集合 的关键特性以及它们如何简化并优化你的代码。
创建集合
创建集合最简单的方法是将一个数组传递给 collect()
方法
$collection = collect(1, 2, 3, 4, 5);
当使用 Eloquent 模型 和 查询构造器 时,它也将默认返回一个 集合
$users = User::query()
->where('is_active', true)
->get();
数据过滤
laravel 集合 拥有很多不同的方法,允许我们过滤集合中的数据。我将向您展示一些用于此目的的方法。
filter()
这是在 集合 中过滤数据的常用方法。它将删除所有在提供的回调中返回 false
的项。
$users = collect([
['name' => 'John Doe', 'is_active' => true],
['name' => 'Mary Doe', 'is_active' => true],
['name' => 'Peter Doe', 'is_active' => false],
]);
$filtered = $users->filter(fn ($user) => $user['is_active']);
// [
// ['name' => 'John Doe', 'is_active' => true],
// ['name' => 'Mary Doe', 'is_active' => true],
// ]
你还可以调用没有回调的 filter()
方法。在这种情况下,它将删除所有如 null
、false
、''
、0
、[]
之类的 false/empty
项。
需要注意的是,该方法不会对原始 集合 进行任何更改,它将创建一个新的 集合,其中包含经过过滤的项。
where()
与用于 Eloquent 查询的 where()
方法类似,where()
方法也可以根据键/值来过滤数据。
$users = collect([
['name' => 'John Doe', 'age' => 15],
['name' => 'Mary Doe', 'age' => 20],
['name' => 'Peter Doe', 'age' => 30],
['name' => 'George Doe', 'age' => 20],
]);
$filtered = $users->where('age', 20);
// [
// ['name' => 'Mary Doe', 'age' => 20],
// ['name' => 'George Doe', 'age' => 20],
// ]
您还可以将比较运算符作为第二个参数传递,就像 Eloquent 的 where()
方法一样。
$users = collect([
['name' => 'John Doe', 'age' => 15],
['name' => 'Mary Doe', 'age' => 20],
['name' => 'Peter Doe', 'age' => 30],
['name' => 'George Doe', 'age' => 20],
]);
$filtered = $users->where('age', '>=', 20);
// [
// ['name' => 'Mary Doe', 'age' => 20],
// ['name' => 'Peter Doe', 'age' => 30],
// ['name' => 'George Doe', 'age' => 20],
// ]
请注意,where()
方法仅检查值是否相同,而不是类型,因此 20
和 '20'
将视为相同。如果您想同时检查值和类型,则可以使用 whereStrict()
方法。
您还可以使用 whereIn()
方法来过滤多个值,以及使用 whereBetween()
方法来过滤范围值。
$users = collect([
['name' => 'John Doe', 'age' => 15],
['name' => 'Mary Doe', 'age' => 20],
['name' => 'Peter Doe', 'age' => 30],
['name' => 'George Doe', 'age' => 20],
]);
$filtered = $users->whereIn('age', [20, 30]);
// [
// ['name' => 'Mary Doe', 'age' => 20],
// ['name' => 'Peter Doe', 'age' => 30],
// ['name' => 'George Doe', 'age' => 20],
// ]
$users = collect([
['name' => 'John Doe', 'age' => 15],
['name' => 'Mary Doe', 'age' => 20],
['name' => 'Peter Doe', 'age' => 30],
['name' => 'George Doe', 'age' => 20],
]);
$filtered = $users->whereBetween('age', [15, 20]);
// [
// ['name' => 'John Doe', 'age' => 15],
// ['name' => 'Mary Doe', 'age' => 20],
// ['name' => 'George Doe', 'age' => 20],
// ]
需要注意的是,这些方法不会对原始的 Collection 产生任何改变,而是创建一个全新的包含过滤项的 Collection。
first()
此方法返回返回给定回调函数的 Collection 的第一个元素。
$users = collect([
['name' => 'John Doe', 'age' => 15],
['name' => 'Mary Doe', 'age' => 20],
['name' => 'Peter Doe', 'age' => 30],
]);
$filtered = $users->first(fn ($user) => $user['age'] > 18);
// ['name' => 'Mary Doe', 'age' => 20]
您也可以不提供任何回调就能调用 first()
方法。在这种情况下,它将返回 Collection 的第一个元素。
$users = collect([
['name' => 'John Doe', 'age' => 15],
['name' => 'Mary Doe', 'age' => 20],
['name' => 'Peter Doe', 'age' => 30],
]);
$filtered = $users->first(fn ($user) => $user['age'] > 18);
// ['name' => 'John Doe', 'age' => 15]
如果您在找不到结果时想抛出异常,可以使用 firstOrFail()
方法。在这种情况下,如果没有找到任何项,它将引发一个 Illuminate\Support\ItemNotFoundException
异常。
last()
此方法返回返回给定回调函数的最后一个元素。
$users = collect([
['name' => 'John Doe', 'age' => 15],
['name' => 'Mary Doe', 'age' => 20],
['name' => 'Peter Doe', 'age' => 30],
]);
$filtered = $users->last(fn ($user) => $user['age'] > 18);
// ['name' => 'Peter Doe', 'age' => 30]
您也可以不提供任何回调就能调用 last()
方法。在这种情况下,它将返回 Collection 的最后一个元素。
$users = collect([
['name' => 'John Doe', 'age' => 15],
['name' => 'Mary Doe', 'age' => 20],
['name' => 'Peter Doe', 'age' => 30],
]);
$filtered = $users->first(fn ($user) => $user['age'] > 18);
// ['name' => 'Peter Doe', 'age' => 30]
only()
此方法可以根据键从 Collection 过滤所需项。
$user = collect([
'id' => 1,
'name' => 'John Doe',
'email' => '[email protected]',
'username' => 'john_doe',
]);
$filtered = $user->only(['name', 'email']);
// ['name' => 'John Doe', 'email' => '[email protected]']
需要注意的是,该方法不会对原始 集合 进行任何更改,它将创建一个新的 集合,其中包含经过过滤的项。
except()
此方法可用于基于键从 Collection 过滤不想要的项。
$user = collect([
'id' => 1,
'name' => 'John Doe',
'email' => '[email protected]',
'username' => 'john_doe',
]);
$filtered = $user->except(['name', 'email']);
// ['id' => 1, 'username' => 'john_doe']
需要注意的是,该方法不会对原始 集合 进行任何更改,它将创建一个新的 集合,其中包含经过过滤的项。
数据格式化和转换
对于应用程序在获取一些数据后,循环遍历以转换值并将格式化的值推入临时变量来说,这相当常见。而不是这样做,我们可以使用 map()
方法,它将在 Collection 的每个元素上执行给定的回调函数,并返回一个新 Collection,包含转换/格式化的值。
$users = collect([
['name' => 'John Doe', 'email' => '[email protected]', 'is_active' => true],
['name' => 'Mary Doe', 'email' => '[email protected]', 'is_active' => true],
['name' => 'Peter Doe', 'email' => '[email protected]', 'is_active' => true],
]);
$userModels = $users->map(fn ($user) => new User($user));
集合调试
有时我们需要调试我们的 Collections 的值,而 Laravel Collections 提供了两个方法来解决我们这个问题。
dump()
此方法将 Collection 道具导出并继续执行脚本。
dd()
此方法将 Collection 道具导出并结束脚本执行。
隐藏的宝石
除了以上章节中介绍的方法之外,还有一些方法使用得不是很多,也不是非常知名,但它们可能会根据我们的工作内容产生重要作用。以下是我想列举的一些我认为您应该了解的方法。
undot()
此方法可以将点符号字符串转换为数组。
$data = collect([
'user.first_name' => 'John',
'user.last_name' => 'Doe',
'user.email' => '[email protected]',
'user.social.twitter' => '@john_doe',
'user.social.github' => 'JohnDoe',
]);
$user = $data->undot();
// [
// "user" => [
// "first_name" => "John",
// "last_name" => "Doe",
// "email" => "[email protected]",
// "social" => [
// "twitter" => '@john_doe',
// "github" => 'JohnDoe',
// ],
// ],
// ]
partition()
此方法根据给定的回调函数将 Collection 项分别到两个不同的集合中。对于返回给定回调函数为 true
的项,它们将被推到第一个 Collection 中,对于返回 false
的项,将被推到第二个 Collection 中。
$users = collect([
['name' => 'John Doe', 'is_active' => true],
['name' => 'Mary Doe', 'is_active' => false],
['name' => 'Peter Doe', 'is_active' => true],
]);
[$activeUsers, $inactiveUsers] = $users->partition(fn ($user) => $user['is_active']);
$activeUsers->all();
// [
// ['name' => 'John Doe', 'is_active' => true],
// ['name' => 'Peter Doe', 'is_active' => true],
// ]
$inactiveUsers->all();
// [
// ['name' => 'Mary Doe', 'is_active' => false],
// ]
reject()
这是 filter()
方法的对立面,但它并不那么知名。它将移除所有返回给定回调函数为 true
的项。
$users = collect([
['name' => 'John Doe', 'is_active' => true],
['name' => 'Mary Doe', 'is_active' => true],
['name' => 'Peter Doe', 'is_active' => false],
]);
$filtered = $users->reject(fn ($user) => $user['is_active']);
// [
// ['name' => 'Peter Doe', 'is_active' => false],
// ]
random()
此方法从 Collection 中返回一个随机元素。
$data = collect([1, 2, 3, 4, 5]);
$data->random();
// 3 - randomly selected
如果您想检索多个项,可以传递一个整数作为参数。
$data = collect([1, 2, 3, 4, 5]);
$data->random(2);
// [2, 3] - randomly selected
isEmpty()
此方法返回 true
如果集合中没有元素,或者如果至少有一个元素,则返回 false
。
collect([])->isEmpty(); // true
collect([1])->isEmpty(); // false
isNotEmpty()
此方法与 isEmpty()
方法相反。如果没有元素,则返回 true
,至少有一个元素则返回 false
。
collect([])->isNotEmpty(); // false
collect([1])->isNotEmpty(); // true
高阶消息
高阶消息就像是我们在集合中应用常见操作的快捷方式。支持此功能的方法有:average()
、avg()
、contains()
、each()
、every()
、filter()
、first()
、flatMap()
、groupBy()
、keyBy()
、map()
、max()
、min()
、partition()
、reject()
、skipUntil()
、skipWhile()
、some()
、sortBy()
、sortByDesc()
、sum()
、takeUntil()
、takeWhile()
和 unique()
。
想象一下,你需要发送一份新闻简报到所有订阅用户。使用这个功能,你可以像这样做。
User::query()
->where('receive_newsletter', true)
->each
->sendNewsletter();
懒集合
集合本身功能强大,而 懒集合 则通过使用生成器进一步扩展了其功能,因此我们可以在保持低内存使用的同时处理大量数据。
想象一下,我们在数据库中有数百万个产品,并且需要对这些产品执行一些操作,我们可以使用 Eloquent/Query Builder 的 cursor()
方法来返回一个 懒集合 而不是常规的 集合。
$payments = Payment::query()
->where('is_accepted', true)
->cursor()
->map(fn ($payment) => $this->formatPaymentData($payment));
foreach ($payments as $payment) {
// LOGIC HERE
}
在上面的例子中,将对数据库执行单个查询,但它一次只在内存中保存一个元素。此外,map()
回调不会立即执行,而只在我们遍历 foreach
语句中的每个单独元素时才会执行。
创建您自己的集合方法
除了集合预先提供的所有惊人的方法外,由于它们是“宏可用的”,我们还可以创建自己的方法。这意味着我们可以使用 macro()
方法通过我们自己的方法来扩展它们。为了做到这一点,我们需要在我们的 AppServiceProvider
类的 boot()
方法中添加我们的新自定义方法。
class AppServiceProvider extends ServiceProvider
{
public function boot()
{
Collection::macro('toSlug', function () {
return $this->map(fn ($value) => Str::slug($value, '-'));
});
}
}
总结
这只是 Laravel 集合上可用的许多强大方法中的几个例子。通过使用这些方法,你可以轻松高效地操作数据,使你的代码更加 可读 和 易于维护。
希望你喜欢这篇文章,如果你喜欢,别忘了与你的朋友分享这篇文章!!!再见! :wink
driesvints, zaki, sabotazh, surajitbasak109, ahmed3bead, alexporto90, malozaibi, hazratbilal98, sfaut, ahmad-mohammad-kouja 以及更多的人喜欢了这篇文章