Коллекции
Запрос Eloquent возвращает не массив, а коллекцию — объект с десятками методов для обработки данных. Методы соединяются в цепочку, и код читается как описание того, что нужно получить.
Создание
Коллекцию возвращают get() и all(). Из обычного массива её делает функция collect():
$numbers = collect([1, 2, 3, 4, 5]);
$posts = Post::all();Преобразование и отбор
map() изменяет каждый элемент, filter() оставляет подходящие:
$titles = $posts->map(fn ($post) => strtoupper($post->title));
$popular = $posts->filter(fn ($post) => $post->views > 1000);
$even = collect([1, 2, 3, 4])->filter(fn ($n) => $n % 2 === 0)->values();values() перенумеровывает ключи после фильтрации.
Значения одного поля
$titles = $posts->pluck('title');
$titlesById = $posts->pluck('title', 'id');
$list = $posts->pluck('title')->implode(', ');Поиск
$first = $posts->first();
$firstPopular = $posts->first(fn ($post) => $post->views > 1000);
$post = $posts->firstWhere('slug', 'hello');
$hasDrafts = $posts->contains(fn ($post) => !$post->is_published);Подсчёты
$total = $orders->sum('total');
$average = $orders->avg('total');
$biggest = $orders->max('total');
$count = $orders->count();Эти методы считают по уже загруженным данным, без нового запроса к базе.
Сортировка и группировка
$sorted = $posts->sortByDesc('views')->values();
$byCategory = $posts->groupBy('category_id');
$counts = $posts->countBy('category_id');
[$published, $drafts] = $posts->partition(fn ($post) => $post->is_published);groupBy() возвращает коллекцию коллекций, где ключи — значения поля. partition() делит коллекцию на две по условию.
Части коллекции
$top = $posts->take(3);
$rest = $posts->skip(3);
$rows = $posts->chunk(4);
$unique = collect([1, 2, 2, 3])->unique()->values();chunk(4) разбивает на группы по четыре — удобно для вывода карточек рядами.
Цепочка
$report = Order::with('user')->get()
->filter(fn ($order) => $order->status === 'paid')
->groupBy(fn ($order) => $order->user->name)
->map(fn ($orders) => $orders->sum('total'))
->sortDesc();Получится сумма оплаченных заказов по каждому покупателю, от большей к меньшей.
Коллекция или запрос
Методы коллекций работают в памяти PHP, а методы построителя — в базе данных. Всё, что можно сделать запросом, делайте запросом:
| Задача | В базе | В памяти |
|---|---|---|
| Отобрать опубликованные | Post::where(...)->get() | Post::all()->where(...) |
| Посчитать | Post::count() | Post::all()->count() |
Правая колонка загружает всю таблицу, чтобы потом выбросить большую часть.
Частая ошибка
Post::all()->count() и Post::count() дают одно число, но первое загружает в память каждую строку таблицы. На десяти записях разницы нет, на миллионе сайт упадёт от нехватки памяти. Фильтруйте и считайте в базе, а коллекции используйте для того, что уже загружено.