支持Laravel.io的持续发展 →

Laravel Collections: 工匠的艺术指南

2023 年 1 月 16 日 阅读时间:9 分钟

简介

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() 方法。在这种情况下,它将删除所有如 nullfalse''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],
// ]

您还可以将比较运算符作为第二个参数传递,就像 Eloquentwhere() 方法一样。

$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 Buildercursor() 方法来返回一个 懒集合 而不是常规的 集合

$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

最后更新 1 年前。

driesvints, zaki, sabotazh, surajitbasak109, ahmed3bead, alexporto90, malozaibi, hazratbilal98, sfaut, ahmad-mohammad-kouja 以及更多的人喜欢了这篇文章

25
喜欢这篇文章吗? 让作者知道并给他们鼓掌!
wendell_adriel (Wendell Adriel) PHP/Laravel 专业网站构建者😎开源爱好者🔥帮助你提高技能💪在 Web 开发领域拥有 13 多年的经验🤘指导了数十名开发人员🎓

你可能还喜欢这些文章

如何使用Larastan将你的Laravel应用从0提高到9

在Laravel应用执行之前就找出错误是可能的,多亏了Larastan,它是...

阅读文章

无需trait标准化API响应

我注意到大多数用于API响应的库都是用traits实现的,并且...

阅读文章

在你的Laravel项目中通过Discord通知收集反馈

如何在Laravel项目中创建反馈模块,并在收到消息时收到Discord通知...

阅读文章

我们感谢这些令人惊叹的公司 对我们的支持

您的标志在这里?

Laravel.io

解决难题、知识共享和社区建设的Laravel门户。

© 2024 Laravel.io - 版权所有。