Junior: питання на співбесіді з теми «Колекції»
Питання з реальних співбесід з відповідями: Laravel і PHP, бази даних, JavaScript і фронтенд, Git, Docker, API, безпека й архітектура. Тими самими темами, що й тести.
3 питання
Collection - обгортка над масивом із плавним, ланцюжковим API. Eloquent-запити повертають саме колекції.
$names = collect($users)
->filter(fn ($u) => $u->active)
->sortBy('name')
->map(fn ($u) => $u->name)
->values();
Десятки методів: map, filter, reduce, groupBy, pluck, each, sum. Код читається зрозуміліше за вкладені цикли й array_*-функції. Для дуже великих наборів є LazyCollection (на генераторах).
Усі три повертають нову колекцію (чи значення) і не змінюють вихідну.
$prices = collect([100, 250, 40]);
$withVat = $prices->map(fn (int $p) => $p * 1.2); // [120, 300, 48]
$expensive = $prices->filter(fn (int $p) => $p > 50); // [0 => 100, 1 => 250]
$total = $prices->reduce(fn (int $sum, int $p) => $sum + $p, 0); // 390
$prices->all(); // [100, 250, 40] - без змін
map()- перетворює кожен елемент, кількість та сама;filter()- залишає елементи, що пройшли умову (без замикання - прибирає «порожні»);reduce()- зводить колекцію до одного значення будь-якого типу.
Пастка filter(): ключі зберігаються - вийде [0 => 100, 1 => 250], а після видалення середнього елемента було б [0 => ..., 2 => ...]. У JSON такий масив стане об'єктом. Перед відповіддю викликають values().
Мутуючі методи теж є, і їх варто знати, щоб не здивуватися: transform(), push(), put(), pop(), shift(), forget() змінюють саму колекцію.
Для простих сум є готові sum(), avg(), max() - reduce() потрібен для складнішого накопичення.
Model::get() повертає Illuminate\Database\Eloquent\Collection - вона успадковує звичайну колекцію й додає методи для моделей.
$users = User::where('active', true)->get();
$users->find(7); // модель за первинним ключем, без запиту
$users->modelKeys(); // [1, 7, 12]
$users->load('posts'); // жадібно завантажити зв'язок для всіх
$users->loadCount('orders');
$users->contains($someUser); // порівнює моделі за ключем
$users->fresh(); // перечитати з бази
$users->toQuery()->update([...]); // один запит за ключами колекції
$users->except([1, 7]); // без моделей з цими ключами
Що важливо розуміти:
- методи колекції працюють у пам'яті.
$users->where('role', 'admin')фільтрує вже завантажене, аUser::where('role', 'admin')- робить запит. Перше доречне для невеликої вибірки, друге - коли рядків багато; - деякі методи (
map,pluck) повертають звичайну колекцію, якщо результат уже не моделі; load()на колекції - спосіб прибрати N+1, коли моделі отримали безwith().
Для власних методів ($orders->totalPaid()) моделі можна дати свою колекцію атрибутом #[CollectedBy].