Laravel 集合类中 GroupBy 方法的使用技巧

自 Laravel v5.5.29 版本后你可以在 集合 中使用多级分组。让我们来看看这意味着什么,是怎么做到的。

准备

这是一篇关于 Laravel 新特性的文章,但在此之前先让我们看看它以前是什么样的。groupBy 是 Collection 类的一个方法。为了我们的例子我会创建一些数据。Students 将会是已经给定的 User 类的工厂状态。

// 来自 Laravel 的 user 工厂
$factory->define(App\User::class, function (Faker $faker) {
    return [
        'name' => $faker->name,
        'email' => $faker->unique()->safeEmail,
        'password' => '$2y$10$TKh8H1.PfQx37YgCzwiKb.KjNyWgaHb9cbcoQgdIVFlYg7B77UdFm', // secret
        'remember_token' => str_random(10),
    ];
});

// 我们的新的 students 状态
$factory->state(App\User::class, 'students', function (Faker $faker) {
    return [
        'skilllevel' => collect(['beginner', 'intermediate', 'professional'])->random(),
        'teacher' => collect(['Peter', 'Markus', 'Chris'])->random(),
    ];
});

这个新的状态会为用户表添加一些数据,我们有了 skilllevel 和 teacher 这两个新字段和值。为了方便我们会使用路由回调的方式,这样我们就可以很容易的将结果返回到浏览器。

Route::get('/', function () {

    return $students = factory(User::class)
        ->times(3)
        ->states('students')
        ->make();

});

注意:我们使用了 make 方法而没有使用 create 方法,因为我们还没有建立数据库 。

这样就会生成类似于下面的测试数据。

[
    {
        "name": "Jakayla Leffler",
        "email": "ocie70@example.com",
        "skilllevel": "professional",
        "teacher": "Peter"
    },
    {
        "name": "Gustave Cummings II",
        "email": "crona.alexandrea@example.net",
        "skilllevel": "intermediate",
        "teacher": "Markus"
    },
    {
        "name": "Ms. Ethelyn Bergnaum MD",
        "email": "deckow.kelvin@example.net",
        "skilllevel": "beginner",
        "teacher": "Peter"
    }
]

基础示例

我刚刚说了 类似于 是因为我们在工厂方法里使用了 Faker 包,所以每一个结果都会不一样。下一步我们使用 groupBy 方法,通过 skilllevel 字段把我们的数据分组。

return $students->groupBy('skilllevel');

你会看到在我们的结果中使用了 skilllevel 的值作为了新的键名。

{
    "professional": [
        {
            "name": "Jacquelyn Kilback",
            "email": "christopher55@example.net",
            "skilllevel": "professional",
            "teacher": "Chris"
        }
    ],
    "beginner": [
        {
            "name": "Miss Ophelia Ryan Jr.",
            "email": "pollich.tristin@example.net",
            "skilllevel": "beginner",
            "teacher": "Chris"
        },
        {
            "name": "Furman Hahn",
            "email": "blowe@example.net",
            "skilllevel": "beginner",
            "teacher": "Markus"
        }
    ]
}

Finally some new stuff

Till here, nothing is really new. So what is the new feature I was talking about? Patrizio T. made a pull request so that you're able to group collections by multiple levels. Let's take a look at an example for a better understanding of what that means.

return $students->groupBy(['skilllevel','teacher']);

We are passing an array instead of a string to define multiple levels. First the students should be grouped by the skilllevel and then by the teacher. So this is what we get:

{
    "intermediate": {
        "Peter": [
            {
                "name": "Jana McClure III",
                "email": "oliver.pagac@example.com",
                "skilllevel": "intermediate",
                "teacher": "Peter"
            }
        ],
        "Chris": [
            {
                "name": "Rosemarie Barrows",
                "email": "epurdy@example.com",
                "skilllevel": "intermediate",
                "teacher": "Chris"
            }
        ]
    },
    "professional": {
        "Markus": [
            {
                "name": "Katrine Streich",
                "email": "carlee.koepp@example.com",
                "skilllevel": "professional",
                "teacher": "Markus"
            }
        ]
    }
}

This grouping can be helpful when you want to display or compare the data. In this case only Markus has a professional student. Maybe he is already a better teacher?

变得疯狂点

这对我们的例子来说没有意义的,但我们可以将学生们以他们的姓名和电子邮箱及其他来分组:

return $students->groupBy(['skilllevel','teacher', 'name', 'email']);

这里是一些疯狂的嵌套结构,但他也有有可能的 :-)

{
    "professional": {
        "Peter": {
            "Mrs. Ella McClure": {
                "forest.bernier@example.com": [
                    {
                        "name": "Mrs. Ella McClure",
                        "email": "forest.bernier@example.com",
                        "skilllevel": "professional",
                        "teacher": "Peter"
                    }
                ]
            }
        },
        "Chris": {
            "Miss Assunta Predovic PhD": {
                "amari.klocko@example.com": [
                    {
                        "name": "Miss Assunta Predovic PhD",
                        "email": "amari.klocko@example.com",
                        "skilllevel": "professional",
                        "teacher": "Chris"
                    }
                ]
            }
        }
    },
    "intermediate": {
        "Markus": {
            "Keshawn Crona DVM": {
                "vkilback@example.org": [
                    {
                        "name": "Keshawn Crona DVM",
                        "email": "vkilback@example.org",
                        "skilllevel": "intermediate",
                        "teacher": "Markus"
                    }
                ]
            }
        }
    }
}

结论

我真的很喜欢现在用多个值来分组一个集合是如此简单。 语法简介而且效果很好。 对于这个新特性你要其他好的例子吗? 通过 Twitter 来告知我们。

本文中的所有译文仅用于学习和交流目的,转载请务必注明文章译者、出处、和本文链接
我们的翻译工作遵照 CC 协议,如果我们的工作有侵犯到您的权益,请及时联系我们。

原文地址:https://christoph-rumpel.com/2018/01/gro...

译文地址:https://learnku.com/laravel/t/8713/the-u...

本帖已被设为精华帖!
本文为协同翻译文章,如您发现瑕疵请点击「改进」按钮提交优化建议
《L03 构架 API 服务器》
你将学到如 RESTFul 设计风格、PostMan 的使用、OAuth 流程,JWT 概念及使用 和 API 开发相关的进阶知识。
《L02 从零构建论坛系统》
以构建论坛项目 LaraBBS 为线索,展开对 Laravel 框架的全面学习。应用程序架构思路贴近 Laravel 框架的设计哲学。
讨论数量: 3
lol173

好强

6年前 评论

自从用了这个新特性后省事多了

5年前 评论

讨论应以学习和精进为目的。请勿发布不友善或者负能量的内容,与人为善,比聪明更重要!