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

自 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 来告知我们。


Practice makes perfect.

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

译文地址:https://laravel-china.org/topics/8713/th...

本帖已被设为精华帖!
《L03 构架 API 服务器》
你将学到如 RESTFul 设计风格、PostMan 的使用、OAuth 流程,JWT 概念及使用 和 API 开发相关的进阶知识。
《L05 电商实战》
从零开发一个电商项目,功能包括电商后台、商品 & SKU 管理、购物车、订单管理、支付宝支付、微信支付、订单退款流程、优惠券等
讨论数量: 3
lol173

好强

6个月前

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

4个月前

这个好

4个月前

  • 请注意单词拼写,以及中英文排版,参考此页
  • 支持 Markdown 格式, **粗体**、~~删除线~~、`单行代码`, 更多语法请见这里 Markdown 语法
  • 支持表情,使用方法请见 Emoji 自动补全来咯,可用的 Emoji 请见 :metal: :point_right: Emoji 列表 :star: :sparkles:
  • 上传图片, 支持拖拽和剪切板黏贴上传, 格式限制 - jpg, png, gif
  • 发布框支持本地存储功能,会在内容变更时保存,「提交」按钮点击时清空
  请勿发布不友善或者负能量的内容。与人为善,比聪明更重要!