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

Усе про Laravel - в одному місці

Україномовна спільнота розробників: документація Laravel українською, вакансії, статті, події, відео та підготовка до співбесід

Будуй спільноту разом з нами - реєструйся та додавай свій контент

Популярні статті

Найбільш читані матеріали спільноти

Pest 5: Tia Engine, плагін для AI-агентів і evals для LLM
Новини 29 липня 2026 70

Pest 5: Tia Engine, плагін для AI-агентів і evals для LLM

На першому дні Laracon US 2026 Нуно Мадуро представив Pest 5. Головне - Tia Engine, що переганяє лише зачеплені змінами тести й скорочує десятихвилинний прогін до кількох секунд, плюс плагіни для AI-агентів, evals, PHPStan і Rector.

Популярні вакансії

Пропозиції, які найчастіше переглядають

Готуєтесь до співбесіди?

Ми зібрали найпопулярніші питання з реальних співбесід на позиції Laravel розробника для рівнів Junior, Middle та Senior.

171+ питань · Junior · Middle · Senior Режим флеш-карток для тренування

Laravel Tips & Tricks

Швидкі та корисні сніппети коду від спільноти

Tips 28 серпня 2026

pipe() - кастомна логіка у ланцюжку

Потрібно застосувати складну логіку до всієї колекції?

pipe() передає в callback усю колекцію і повертає те, що callback повернув.

Переваги:

  • Гнучка логіка
  • Розбиття складних ланцюжків
  • Умовні трансформації
  • Дебаг

Різниця з map():

  • map() - елемент за елементом
  • pipe() - вся колекція одразу

Порада: використовувати іменовані функції для читабельності.

$result = $users
  ->where('active', true)
  ->pipe(fn($c) => $c->sortBy('last_login')->take(10))
  ->values();

// Умовне сортування
$posts = Post::all()->pipe(function ($posts) use ($request) {
  return $request->sort === 'popular'
    ? $posts->sortByDesc('views')
    : $posts->sortByDesc('created_at');
});

// Дебаг
$result = $users
  ->where('active', true)
  ->pipe(fn($c) => tap($c, fn($c) => logger($c->count())))
  ->where('role', 'admin');
Tips 26 серпня 2026

partition() - поділ колекції на дві частини

Потрібно поділити користувачів на активних і неактивних?

partition() повертає одразу дві групи.

Різниця з filter():

  • filter() повертає лише truthy
  • partition() повертає truthy і falsy одразу

Сценарії:

  • Валідні / невалідні дані
  • Passed / failed
  • Approved / pending

Порада: зручно для різних обробок двох груп.

4
[$active, $inactive] = $users->partition(fn($u) => $u->active);

// Дві різні обробки
$active->each(fn($u) => ...);
$inactive->each(fn($u) => ...);

// Валідація
[$valid, $invalid] = $orders->partition(fn($o) =>
  $o->total > 0 && $o->email !== null
);

// Студенти
[$passed, $failed] = $students->partition(
  fn($s) => $s->score >= 60
);
Tips 24 серпня 2026

groupBy() - організація даних як у таблиці

Потрібно показати пости за категоріями? Вкладені цикли не потрібні.

groupBy() групує колекцію за ключем.

Як працює:

Повертає масив груп, де кожна група - окрема колекція.

Розширені можливості:

  • Групування за callback
  • Кілька рівнів групування
  • Dot notation

Порада: ідеально для аналітики, звітів і категоризації.

// Групування за категорією
$byCategory = $posts->groupBy('category_id');

// Групування за роком
$byYear = $posts->groupBy(fn($p) => $p->created_at->year);

// Доступ до груп
foreach ($byCategory as $categoryId => $posts) {
  echo "Category {$categoryId}: {$posts->count()} posts\n";
}

// Кілька рівнів
$byYearMonth = $posts->groupBy([
  fn($p) => $p->created_at->year,
  fn($p) => $p->created_at->month,
]);

// Групування по зв'язку
$byPostTitle = $comments->groupBy('post.title');

// Практичний приклад - суми продажів
$report = $orders->groupBy('status')
  ->map(fn($group) => $group->sum('total'));
Tips 21 серпня 2026

filter() vs reject() - очищення даних

Потрібно прибрати частину елементів? Писати складні if не обов'язково.

filter() залишає елементи, що відповідають умові. reject() прибирає елементи, що відповідають умові.

Різниця:

  • filter() - залишає truthy
  • reject() - прибирає truthy
  • Обидва повертають нову колекцію

Розширено:

Для простих порівнянь краще where(), whereIn(), whereBetween().

Порада: filter() без callback прибирає всі falsy (null, false, 0, '', []).

// filter() - тільки активні
$active = $users->filter(fn($u) => $u->active === true);

// reject() - видалити неактивних
$active = $users->reject(fn($u) => $u->active === false);

// filter() без callback
$values = collect([1, 2, null, 3, false, '', 4]);
$cleaned = $values->filter();
// [1, 2, 3, 4]

// where()
$admins = $users->where('role', 'admin');
$verified = $users->where('email_verified_at', '!=', null);

// whereIn()
$staff = $users->whereIn('role', ['admin', 'moderator']);

// whereBetween()
$recent = $posts->whereBetween('created_at', [
  now()->subDays(7),
  now()
]);

// Комбінування фільтрів
$result = $users
  ->where('active', true)
  ->whereIn('role', ['admin', 'editor'])
  ->filter(fn($u) => $u->posts_count > 10);
Tips 19 серпня 2026

chunk() - поділ даних на частини

Потрібно обробити 10 000 елементів? Або API обмежує 100 запитів за хвилину?

chunk() розбиває колекцію на менші групи.

Сценарії:

  • Обмеження API
  • Пакетна обробка
  • Керування пам'яттю
  • Прогрес-бар

Відмінність від query chunk():

Collection chunk() працює з уже завантаженими даними. Query chunk() завантажує дані з бази порціями.

Порада: поєднувати з sleep() для API rate limit.

// Поділ на частини по 100
$users = User::all();
$users->chunk(100)->each(function ($batch) {
  $this->sendBatchEmail($batch);
});

// API rate limit
$products = collect($apiProducts);
$products->chunk(50)->each(function ($batch) {
  $this->syncToDatabase($batch);
  sleep(1);
});

// Прогрес
$done = 0;

$users->chunk(100)->each(function ($batch) use (&$done) {
  $batch->each(fn($u) => $this->process($u));
  $done += $batch->count();
  echo "Progress: {$done}\n";
});

// Комбінування з іншими методами
$users->chunk(100)->map(function ($chunk) {
  return $chunk->pluck('email');
});
Tips 17 серпня 2026

map() vs transform() - трансформація колекцій

Потрібно змінити кожен елемент колекції?

map() і transform() роблять це, але працюють по-різному.

Різниця:

  • map() повертає НОВУ колекцію, оригінал залишається без змін
  • transform() змінює оригінальну колекцію

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

  • map() - коли початкові дані потрібні пізніше
  • transform() - коли треба зекономити пам'ять на великих колекціях

Порада: map() дозволяє повністю змінювати структуру, transform() зберігає ключі.

// map() - створює нову колекцію
$users = User::all();
$names = $users->map(function ($user) {
  return strtoupper($user->name);
});

// transform() - змінює оригінал
$users = User::all();
$users->transform(function ($user) {
  $user->name = strtoupper($user->name);
  return $user;
});

// map() з короткими функціями
$prices = collect([100, 200, 300]);
$withTax = $prices->map(fn($p) => $p * 1.2);

// Повна зміна структури
$formatted = $users->map(fn($user) => [
  'id' => $user->id,
  'label' => "{$user->name} ({$user->email})"
]);

// mapWithKeys - власні ключі
$users->mapWithKeys(fn($user) =>
  [$user->email => $user->name]
);
Tips 14 серпня 2026

pluck() - витягуй значення професійно

Потрібен масив ID? Організовувати цикл і додавати значення вручну не потрібно.

pluck() дістає значення стовпця в простий масив. В один рядок.

Розширені можливості:

  • Pluck із ключем - створює асоціативний масив
  • Pluck у зв'язках - без N+1
  • Pluck на кілька рівнів - через dot notation

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

  • Формування select-опцій
  • Отримання ID для whereIn()
  • Створення lookup-масивів

Порада: використовувати pluck() безпосередньо на query builder - ефективніше, ніж завантажувати моделі.

3
// Погано: цикл і ручне збирання
$ids = [];
foreach ($users as $user) {
  $ids[] = $user->id;
}

// Добре: один рядок
$ids = $users->pluck('id');
// [1, 2, 3, 4, 5]

// Із ключем
$userNames = $users->pluck('name', 'id');
// [1 => 'John', 2 => 'Jane', 3 => 'Bob']

// Безпосередньо з бази - ефективніше
$emails = User::pluck('email');
$emailsById = User::pluck('email', 'id');

// Dot notation
$posts = Post::with('author')->get();
$authorNames = $posts->pluck('author.name');

// Кілька рівнів
$comments = Comment::with('post.author')->get();
$authors = $comments->pluck('post.author.name');

// Для select
$countries = Country::pluck('name', 'code');
// ['US' => 'United States', 'GB' => 'United Kingdom']
Tips 12 серпня 2026

withDefault() - ніяких null при зв'язках

Постійно перевіряєте, чи існує зв'язок, перед доступом до нього?

withDefault() повертає "порожню" модель замість null.

Переваги:

  • Менше if ($user->profile)
  • Чистіші Blade-шаблони
  • Можливість задати дефолтні значення
4
// User model
public function profile()
{
  return $this->hasOne(Profile::class)
    ->withDefault([
      'bio' => 'No bio provided',
      'avatar' => 'default.png',
      'website' => null,
    ]);
}

// Без перевірок на null
{{ $user->profile->bio }}
// Динамічні дефолти
public function profile()
{
  return $this->hasOne(Profile::class)
    ->withDefault(function ($profile, $user) {
      $profile->bio = "Member since {$user->created_at->year}";
    });
}

// BelongsTo з дефолтом
public function author()
{
  return $this->belongsTo(User::class, 'author_id')
    ->withDefault([
      'name' => 'Guest',
      'email' => 'noreply@example.com',
    ]);
}

// У Blade
{{ $post->author->name }} // Ніколи не null
Tips 10 серпня 2026

whereBetween() - запити по діапазонах

Фільтруєте по діапазону через дві where-умови? Читається важко.

whereBetween() робить те саме, але чистіше.

Кейси:

  • Діапазони дат
  • Фільтр по ціні
  • Вік
  • Будь-які числові інтервали

Є протилежність - whereNotBetween().

4
// ПОГАНО
$orders = Order::where('total', '>=', 100)
  ->where('total', '<=', 500)
  ->get();

// ДОБРЕ
$orders = Order::whereBetween('total', [100, 500])->get();

// Діапазон дат
$orders = Order::whereBetween('created_at', [
  now()->subDays(30),
  now()
])->get();

// Вік
$users = User::whereBetween('age', [18, 65])->get();

// Виключити діапазон
$products = Product::whereNotBetween('price', [100, 200])->get();
Tips 07 серпня 2026

upsert() - масовий insert/update

Треба масово вставити або оновити дані?

upsert() робить insert або update у межах одного запиту.

Як працює:

  • Вказуєте унікальні колонки для пошуку
  • Якщо запис існує - оновлюється
  • Якщо ні - вставляється

Порада: ідеально для синхронізації з зовнішніми сервісами.

// Масове оновлення/створення користувачів
User::upsert(
  [
    ['email' => 'john@ex.com', 'name' => 'John', 'age' => 30],
    ['email' => 'jane@ex.com', 'name' => 'Jane', 'age' => 25],
    ['email' => 'bob@ex.com', 'name' => 'Bob', 'age' => 35],
  ],
  ['email'], // Унікальне поле
  ['name', 'age'] // Поля для оновлення
);

Вітрина проєктів

Проєкти, створені українською спільнотою на Laravel

Проєкт тижня
Громада

Громада

Громада - це платформа, де мешканці вашого району діляться новинами, пропонують послуги, допомагають одне одному та будують справжню спільноту

Svi-RAG - Інтелектуальний ШІ-консультант

Svi-RAG - Інтелектуальний ШІ-консультант

Інтелектуальний ШІ-консультант для вашого сайту, який автоматизує підтримку клієнтів та генерує ліди 24/7. Сервіс миттєво відповідає на запитання користувачів, використовуючи виключно завантажену вами базу знань (RAG-система на базі Gemini та Postgres pgvector). Якщо клієнту потрібна допомога людини, чат автоматично сповіщає та підключає живого менеджера до діалогу без втрати контексту розмови.

Екосистема Laravel

Пакети та інструменти, які прискорять вашу розробку

Bagisto

bagisto/bagisto

Bagisto — це платформа для електронної комерції, побудована на Laravel. Вона надає готове рішення для створення та управління інтернет-магазинами з підтримкою каталогу товарів, замовлень, платежів та клієнтів.

27,987 v2.4.10 12 21

Laravel Query Builder

spatie/laravel-query-builder

Легко будуйте Eloquent-запити на основі запитів від API.

4,461 7.3.3 13 10

Ray

spatie.be/products/ray

Настільний додаток для візуального дебагінгу Laravel та PHP проектів від Spatie.

Laravel Herd

herd.laravel.com

Швидке середовище для локальної розробки на macOS та Windows без використання Docker. Включає PHP, Nginx, dnsmasq, Node.js та інші інструменти "з коробки".

Перевір свої знання

Пройди інтерактивне тестування та дізнайся свій реальний рівень. Доступні тести для Junior, Middle та Senior розробників.

7 тестів
Junior · Middle · Senior
Публічний результат

Ми в медіа

Публікації про Laravel Ukraine на сторонніх майданчиках

Готові долучитися до спільноти?

Створіть профіль, щоб зберігати статті, відстежувати вакансії та потрапити на карту розробників.