Encodera

Спасибо, что читаете!

Пожертвуйте сайту, мы стараемся ради вас.

Оглавление

Коллекции

Запрос 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() дают одно число, но первое загружает в память каждую строку таблицы. На десяти записях разницы нет, на миллионе сайт упадёт от нехватки памяти. Фильтруйте и считайте в базе, а коллекции используйте для того, что уже загружено.

Спасибо, что читаете!

Пожертвуйте сайту, мы стараемся ради вас.