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 协议,如果我们的工作有侵犯到您的权益,请及时联系我们。
好强
自从用了这个新特性后省事多了
这个好