Блог Vaden Pro

Все о самостоятельном создании и продвижении сайтов

6 примеров использования Collections в Laravel

Раздел: 

Collections относятся к полезным, но часто забываемым, компонентам Laravel. В данной статье рассмотрено несколько простых и полезных советов по манипулированию данными, используйте их.

Laravel Collections

Предупреждение!

Это статья не о «лучших примерах» в разработке. Здесь показано лишь несколько приемов, которые могут быть полезны в правильном месте Вашего кода. Не применяйте их слепо в проектах на 100 000+ строк и не жалуйтесь мне потом, что ваш сервер после такого приказал долго жить, ок?

Документацию коллекций в Laravel можно глянуть тут

Начнем с создания следующей таблицы и пустого Eloquent Model класса под названием Person для нее:

CREATE TABLE `people` (
  `id` int(10) unsigned NOT NULL AUTO_INCREMENT,
  `first_name` varchar(255) COLLATE utf8_unicode_ci NOT NULL,
  `last_name` varchar(255) COLLATE utf8_unicode_ci NOT NULL,
  `type` varchar(50) COLLATE utf8_unicode_ci NOT NULL
  PRIMARY KEY (`id`)
) ENGINE=MyISAM  DEFAULT CHARSET=utf8 COLLATE=utf8_unicode_ci;
 
INSERT INTO `people` (`id`, `first_name`, `last_name`, `type`) VALUES
(1, 'Jeff', 'Madsen', 'programmer'),
(2, 'Mickey', 'Mouse', 'engineer'),
(3, 'Daffy', 'Duck', 'critic'),
(4, 'Mighty', 'Mouse', 'programmer');

Пример №1: используйте find()

Что? find()? Что за чепуха для новичков? Я знаю все о его использовании!

Да неужели? А как насчет такого:

// Возвращает одну строку как коллекцию
$collection = App\Person::find([1]);
dd($collection);
 
// Может возвращать несколько строк как коллекцию
$collection = App\Person::find([1, 2, 3]);
dd($collection);

Работать подобным образом, зная что мы всегда получим возврат Collection, может быть действительно крайне удобно.

Пример №2: $collection->where()

Используя данные представленные выше, как бы мы могли поместить всех программистов, всех инженеров и всех критиков в раздельные массивы? Использовать три запроса? Ни чего подобного!

$collection = App\Person::all();
 
$programmers =  $collection->where('type', 'programmer');
$critic =  $collection->where('type', 'critic');
$engineer =  $collection->where('type', 'engineer');
 
dd($engineer);

В примере выше я воспользовался ::all(), но возможно Вы хотите ограничиться использованием where, чтобы сделать сводку результатов меньше исходника.

Пример №3: where() & lists() - WP Meta Table Blaster

Вам нравятся данные WordPress, не так ли? Особенно когда Вам необходимо запустить 50 запросов для получения мета-данных одного пользователя? А что если вместо этого использовать:

$collection = App\Person::all();
 
$engineer =  $collection->where('type', 'engineer')->lists('first_name');
dd($engineer);

Этот запрос вернет массив, поскольку мы ищем всех инженеров. В примере с использованием WP, который был упомянут, вы бы скорее всего использовали что-то подобное (предупреждение: пример не проверен и взят из памяти):

// извлекаем все метазаписи для user 1	
$collection = App\WP_Meta::whereUserId(1)->get();
 
// А теперь извлекаем первое и последнее значение
$first_name =  $collection->where('meta_key', 'first_name')->lists('value')[0];
$last_name  =  $collection->where('meta_key', 'last_name')->lists('value')[0];
любые другие поля, которые Вы желаете вырвать

Пример №4: $collection->implode()

Все заметили как как маркетологи умудряются превратить 2-D таблицы Excel в 8-D вещи из матрицы? И они хотят чтобы Вы сделали то же самое в отчетах? Ну, это не поддается лечению, но вы этом примере мы рассмотрим как можно впихнуть one-to-many отношения в одну ячейку:

$collection = App\Person::all();
$names = $collection->implode('first_name', ',');
echo $names;

Я все еще экспериментирую над данным примером, чтобы найти хорошие пути получения имени и фамилии вместе, и проверяю работают ли они правильно в отношениях. Иногда Вам все-же приходится отойти к использованию старых array_maps и loops. Но приятно знать, что подобная возможность все-же существует.

Пример №5: $collection->groupBy()

Если Вы делаете отчеты и не знаете следующих вещей, то Вы тот еще бедняга… Запустите код из примера ниже и наблюдайте:

$collection = App\Person::all();
$grouped = $collection->groupBy('type');
dd($grouped);

Пример №6: подводя итоги

Сначала код, потом какие-то слова. Мы притворимся, что у нас есть 3 разных модели просто прогнав несколько раз одну и ту же с использованием следующего where выражения:

// смысл в том, чтобы действительно совместить результаты от разных моделей
$programmers =  \App\Person::where('type', 'programmer')->get();
$critic      =  \App\Person::where('type', 'critic')->get();
$engineer    =  \App\Person::where('type', 'engineer')->get();
 
$collection  = new Collection;
$all = $collection->merge($programmers)->merge($critic)->merge($engineer);
dd($all);

Теперь предупреждения: будьте осторожны выбирая что сделать с этим набором результатов. Поскольку Вы, по сути, совмещаете сущности различных классов, потому при запуске цикла по ним Вы можете обнаружить некоторые сюрпризы. Некоторые поля данных могут не всегда быть там, или там могут быть мутаторы от различного рода ошибок. А может быть, что сегодня у Вас все отработало отлично, а завтра кто-то пришел и добавил мутатор для одной из моделей и испортил все Ваши результаты.

Так что будьте крайне аккуратны с использованием подобных вещей, убедитесь, что вы используете модели имеющие одинаковый интерфейс, или убедитесь, что у Вас есть Unit Test и Continuous Integration, тобишь используйте это на свой страх и риск. Но когда Вы о всем предупреждены и осторожны, эти примеры могут стать очень полезными инструментами в работе.

Мы рассмотрели только несколько примеров, а их существует огромное количество и Тейлор создает еще больше дополнений и усовершенствований в Laravel 5.1. Потому советую пойти покопаться в Вашем исходном коде и попробовать все Ваши безумные идеи.

Надеюсь данный материал был полезен для Вас!

Перевод статьи Jeff Madsen «6 Tricks for Laravel Collections»