Квест → Как хакнуть форму
Прошли: 77
В Laravel начиная с версии 5.5.29 можно группировать коллекции по нескольким критериям. Давайте посмотрим, что это означает и как это работает.
Итак, эта статья о новой функциональности в фреймворке Laravel. Но прежде чем мы посмотрим как она работает сейчас, давайте посмотрим как она работала раньше. Метод groupBy
является методом класса Collection
. Для наших примеров я создам немного данных, с которыми мы будем работать. Students
будет фабрикой состояний для передаваемого класса User
.
// Default user factory which comes with Laravel $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), ]; }); // Our new students state $factory->state(App\User::class, 'students', function (Faker $faker) { return [ 'skilllevel' => collect(['beginner', 'intermediate', 'professional'])->random(), 'teacher' => collect(['Peter', 'Markus', 'Chris'])->random(), ]; });
Добавленное состояние будет генерить для нас данные пользователей. У нас есть новые поля skilllevel
и teacher
. Для наших примеров мы будем использовать простой роутинг с обычным callback'ом. Таким образом, мы можем быстро и легко вернуть результат в браузер.
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" } ] }
Пока здесь нет ничего действительно нового. Так что же это за новая функция, о которой я говорил? Patrizio T. сделал pull-запрос, так что теперь вы можете группировать коллекции на нескольких уровнях. Чтобы лучше понять, что это значит, давайте взглянем на пример:
return $students->groupBy(['skilllevel','teacher']);
Вместо строки, мы передаем массив, чтобы задать несколько уровней. Сначала коллекция students
должна быть сгруппирована по skilllevel
, а затем по полю teacher
. Итак, вот что мы получили:
{
"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"
}
]
}
}
Эта группировка может быть полезна, когда вы хотите отобразить или сравнить данные. В этом примере только Маркус имеет профессионального студента. Может быть он является лучшим учителем?
Это не имеет смысла для нашего примера, но мы также могли бы группировать студентов по их имени и адресу электронной почты:
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" } ] } } } }
Мне нравится, как теперь просто группировать по нескольким значениям. Синтаксис вполне "прямой", да и работает отлично. Если у вас есть другие хорошие примеры из реальной жизни, делитесь в комментах.