Увійти Реєстрація
Блог Серії
Кар'єра
Вакансії Компанії
Навчання
Документація Співбесіди Тестування Відео
Екосистема
Пакети Ресурси Проєкти
Інше
Події Про нас
Tips 04 серпня 2026

Колекції Eloquent - це більше, ніж масиви

Eloquent повертає Collections, а не масиви.

Помилка - одразу викликати toArray() і працювати як з масивом.

Переваги колекцій:

  • Ланцюжки операцій
  • Зручні методи (map, filter, groupBy, pluck...)
  • Більш виразний код

Порада: тримайте дані в Collection якомога довше.

$users = User::all(); // Collection

// ПОГАНО
foreach ($users->toArray() as $user) {
  echo $user['name'];
}

// ДОБРЕ
$users->each(function ($user) {
  echo $user->name;
});

// Фільтрація й трансформація
$activeAdmins = $users
  ->where('active', true)
  ->where('is_admin', true)
  ->pluck('email');

// Групування
$byRole = $users->groupBy('role');

// Пара "id => name"
$names = $users->pluck('name', 'id');

// Перевірка
$hasAdmin = $users->contains('is_admin', true);
$hasAdult = $users->contains(fn($user) => $user->age > 18);

Коментарі

Увійдіть, щоб залишити коментар

Будьте першим, хто залишить коментар!

Інші поради

Tips 03 серпня 2026

chunkById() - безпечна пакетна обробка

Обробляєте таблицю через chunk() і одночасно змінюєте колонку, за якою фільтруєте? Частина записів буде пропущена.

chunk() гортає сторінки через OFFSET. Якщо запис випадає з вибірки під час обробки, решта зсувається - і цілий пакет ви не побачите.

Як працює chunkById():

Замість OFFSET використовує where('id', '>', $lastId). Зсув вибірки більше не ламає ітерацію.

Коли обов'язково chunkById():

  • Оновлюєте поле, за яким фільтруєте
  • Видаляєте записи під час обходу
  • Будь-яка міграція даних із записом у ту саму таблицю

Порада: сортування задає сам chunkById() - не додавайте власний orderBy(), він його перезапише.

// НЕБЕЗПЕЧНО: пропустить половину записів
User::where('notified', false)
  ->chunk(100, function ($users) {
    foreach ($users as $user) {
      $user->update(['notified' => true]);
      // Вибірка "з'їдається", OFFSET перестрибує записи
    }
  });

// БЕЗПЕЧНО: курсор по первинному ключу
User::where('notified', false)
  ->chunkById(100, function ($users) {
    foreach ($users as $user) {
      $user->update(['notified' => true]);
    }
  });
Tips 31 липня 2026

firstOrFail() - чиста обробка 404

Перевіряєте на існування моделі перед використанням? Багато шаблонного коду.

firstOrFail() кидає виняток, який Laravel перетворює на 404.

Переваги:

  • Менше boilerplate
  • Автоматична обробка помилок
  • REST-friendly

Схожі методи: findOrFail($id), sole().

// ПОГАНО
public function show($id)
{
  $post = Post::find($id);

  if (!$post) {
    abort(404);
  }

  return view('posts.show', compact('post'));
}

// ДОБРЕ
public function show($id)
{
  $post = Post::findOrFail($id);

  return view('posts.show', compact('post'));
}

// За slug
public function showBySlug($slug)
{
  $post = Post::where('slug', $slug)->firstOrFail();

  return view('posts.show', compact('post'));
}
Tips 30 липня 2026

Глобальні скоупи - умови за замовчуванням

Одна й та сама where-умова в кожному запиті? Це не DRY.

Global Scopes додають умову автоматично.

Типові кейси:

  • Multi-tenancy
  • Soft deletes (вже реалізовано через глобальний скоуп)
  • published = true
  • Архівні записи

Можна прибрати через withoutGlobalScope().

// Окремий клас скоупу
class PublishedScope implements Scope
{
  public function apply(Builder $builder, Model $model)
  {
    $builder->where('published', true);
  }
}

// Підключення до моделі
class Post extends Model
{
  protected static function booted()
  {
    static::addGlobalScope(new PublishedScope);
  }
}

// Всі запити - тепер тільки published
$posts = Post::all();
$post = Post::find(1);
Tips 29 липня 2026

Subquery Selects - уникаємо N+1 без eager loading

Потрібен останній пост користувача? Eager loading витягне ВСІ пости.

Subquery-select дозволяє додати обчислювану колонку без завантаження зв'язку.

Коли використовувати:

  • Останній/перший пов'язаний запис
  • count/sum/max/min по зв'язку
  • Коли не потрібні повні дані зв'язку

Продуктивність:

Один запит. Ніякого N+1. Немає зайвих даних.

// ПОГАНО: вантажимо всі пости, щоб узяти останній
$users = User::with('posts')->get();
foreach ($users as $user) {
  echo $user->posts
    ->sortByDesc('created_at')->first()->title;
}

// ДОБРЕ: subquery - тільки заголовок останнього поста
$users = User::select('users.*')
  ->addSelect(['last_post_title' => Post::select('title')
    ->whereColumn('user_id', 'users.id')
    ->latest()
    ->limit(1)
  ])->get();

echo $users[0]->last_post_title;

// Сортування по subquery - без завантаження постів
$users = User::orderByDesc(
  Post::select('created_at')
    ->whereColumn('user_id', 'users.id')
    ->latest()
    ->limit(1)
)->get();
Tips 28 липня 2026

whereHas() проти has() - фільтр за зв'язками

Треба знайти користувачів, у яких є пости? Або тільки з опублікованими постами?

has() перевіряє факт наявності зв'язку. whereHas() дозволяє додати умови до зв'язку.

Різниця:

  • has('posts') - користувачі з будь-якими постами
  • whereHas('posts', fn($q) => ...) - користувачі з конкретними постами

Порада по продуктивності:

Використовуйте has(), коли немає додаткових умов - він простіший.

// Користувачі з будь-якими постами
$users = User::has('posts')->get();

// Користувачі з мінімум 5 постами
$users = User::has('posts', '>=', 5)->get();

// Користувачі тільки з опублікованими постами
$users = User::whereHas('posts', function ($query) {
  $query->where('published', true);
})->get();

// Більш складні умови
$users = User::whereHas('posts', function ($query) {
  $query->where('published', true)
    ->where('views', '>', 1000);
})->get();

// Користувачі без постів
$users = User::doesntHave('posts')->get();

// Комбінування кількох зв'язків
$users = User::has('posts')
  ->whereHas('comments', fn($q) => $q->where('spam', false))
  ->get();
Завантаження...