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

Статті за тегом «Eloquent»

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

No results.
Laravel WhatsApp
Новини 30 червня 2026

Laravel WhatsApp: Два Бекенди За Одним Фасадом

Новий пакет Laravel WhatsApp від Md Mostafijur Rahman дозволяє надсилати та отримувати повідомлення WhatsApp через офіційний Cloud API Meta та неофіційний веб-інтерфейс за допомогою whatsapp-web.js. Обидва варіанти працюють через єдиний фасад WhatsApp::.

Tips 28 червня 2026

Dynamic Scopes - побудова складних фільтрів

Побудова фільтрів пошуку з купою if виразів? Код стає нечитабельним.

Dynamic scopes дозволяють чисто ланцюжити умови.

Патерн:

Кожен scope повертає query builder. Ланцюжи декількох scopes разом.

Просунута техніка:

Використовувати when() всередині scopes для опціональних умов.

Переваги:

  • Повторне використання в контролерах
  • Тестування ізольовано
  • Читабельна побудова запитів

Порада: Створи базовий scope на якому можуть будуватися інші scopes.

// Модель User
public function scopeFilter($query, array $filters)
{
    return $query
        ->when($filters['status'] ?? false,
            fn($q, $status) => $q->where('status', $status))
        ->when($filters['role'] ?? false,
            fn($q, $role) => $q->where('role', $role))
        ->when($filters['search'] ?? false,
            fn($q, $search) => $q->where('name', 'like', "%{$search}%"))
        ->when($filters['date_from'] ?? false,
            fn($q, $date) => $q->whereDate('created_at', '>=', $date))
        ->when($filters['date_to'] ?? false,
            fn($q, $date) => $q->whereDate('created_at', '<=', $date));
}

// Контролер - чисто і просто
public function index(Request $request)
{
    return User::filter($request->only([
        'status', 'role', 'search', 'date_from', 'date_to'
    ]))->paginate();
}
Yammi Audit Log
Новини 26 червня 2026

Yammi Audit Log: пакет для відстеження змін через черги та фонові завдання

Yammi Audit Log - новий пакет для Laravel, який вирішує проблему аудиту змін у моделях через черги. На відміну від звичайних рішень, він зберігає інформацію про того, хто ініціював зміну, навіть якщо вона відбулася через кілька черг або фонових завдань.

Lattice
Новини 19 червня 2026

Lattice: опис Inertia UI на PHP

Lattice - це server-driven UI фреймворк для Laravel, що дозволяє описувати сторінки, форми, таблиці, дії та меню в PHP, а рендерити їх як React-компоненти через Inertia. Сервер стає єдиним джерелом правди для інтерфейсу, а клієнт лише відповідає за його відображення.

Tips 15 червня 2026

insert() vs create() - масові операції правильно

При створенні 1,000 записів в циклі? Кожен create() звертається до бази окремо.

insert() надсилає всі записи одним запитом. В 100 разів швидше.

Компроміс:

  • create() запускає події, заповнює timestamps, повертає модель
  • insert() пропускає все, просто сирий SQL insert

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

  • Заповнення бази даних
  • Імпорт великих наборів даних
  • Фонові пакетні jobs

Порада: Використовувати upsert() для масових операцій insert-or-update в Laravel 8+.

// ПОГАНО: 1000 окремих запитів
foreach ($records as $record) {
    User::create($record); // Повільно
}

// ДОБРЕ: Один запит для всіх
User::insert($records);

// З timestamps
$now = now();
$records = collect($records)->map(function ($record) use ($now) {
    return array_merge($record, [
        'created_at' => $now,
        'updated_at' => $now,
    ]);
})->toArray();

User::insert($records);

// Upsert - вставити або оновити
User::upsert(
    [
        ['email' => 'john@example.com', 'name' => 'John'],
        ['email' => 'jane@example.com', 'name' => 'Jane'],
    ],
    ['email'], // Унікальна колонка
    ['name'] // Оновити ці колонки
);
Tips 10 квітня 2026

sole() - суворе отримання одного результату

Запит має повернути рівно один запис. Повертає нуль або декілька? Це баг.

first() мовчки повертає null. sole() кидає виняток якщо не рівно один.

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

  • Отримання за унікальним ідентифікатором
  • Коли декілька результатів вказують на пошкодження даних
  • Критична бізнес-логіка

Винятки що кидаються:

  • RecordsNotFoundException - нуль результатів
  • MultipleRecordsFoundException - більше одного

Порада: Використовувати у фінансових операціях де очікується рівно один запис.

// ПОГАНО: Мовчки повертає null або перший з багатьох
$user = User::where('email', $email)->first();
// Що якщо є дублікати? Мовчазний баг.

// ДОБРЕ: Гарантує рівно один результат
try {
    $user = User::where('email', $email)->sole();
    // Гарантовано єдиний користувач що підходить
} catch (RecordsNotFoundException $e) {
    // Користувач не знайдений
} catch (MultipleRecordsFoundException $e) {
    // Пошкодження даних - існують дублікати
}

// В обробці рахунків
$invoice = Invoice::where('invoice_number', $number)->sole();
// Дублікати були б серйозним багом

// firstOr vs soleOr
$user = User::where('email', $email)->soleOr(function () {
    throw new UserNotFoundException();
});

// Зі зв'язками
$user = User::with('profile')->where('id', $id)->sole();
Tips 04 квітня 2026

cursor() - потокове передавання великих наборів даних

При експорті 100,000 користувачів. get() завантажує все в пам'ять. Сервер падає.

cursor() передає результати один за одним. Константне використання пам'яті.

Як це працює:

Використовує MySQL cursor. Отримує один запис за раз. Пам'ять залишається низькою.

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

  • Експорт великих наборів даних
  • Обробка величезних таблиць
  • Середовища з обмеженою пам'яттю

Компроміс:

Тримає з'єднання з базою даних відкритим довше. Не для веб-запитів, ідеально для команд.

Порада: Використовувати в консольних командах та jobs, уникай в HTTP контролерах.

// ПОГАНО: Завантажує 100k записів в пам'ять
$users = User::all(); // Може впасти
foreach ($users as $user) {
    $this->export($user);
}

// ДОБРЕ: Потокове передавання один за одним
foreach (User::cursor() as $user) {
    $this->export($user); // Константна пам'ять
}

// В консольній команді
public function handle()
{
    $this->output->progressStart(User::count());

    foreach (User::cursor() as $user) {
        $this->processUser($user);
        $this->output->progressAdvance();
    }

    $this->output->progressFinish();
}

// З умовами
foreach (User::where('active', true)->cursor() as $user) {
    // Обробляти тільки активних користувачів
}
Tips 31 березня 2026

exists() vs count() - розумна перевірка

Перевірка чи користувач має пости? Використання $user->posts->count() > 0 завантажує всі пости.

exists() зупиняється на першому збігу. Набагато швидше.

Різниця:

  • count() підраховує всі записи
  • exists() зупиняється коли знаходить перший

Вплив на продуктивність:

З 10,000 постів - count() завантажує всі, exists() знаходить один і зупиняється.

Порада: Використання exists() для булевих перевірок, count() тільки коли потрібне фактичне число.

// ПОГАНО: Завантажує всі пости, рахує їх
if ($user->posts->count() > 0) {
    echo "Користувач має пости";
}

// ДОБРЕ: Зупиняється на першому пості
if ($user->posts()->exists()) {
    echo "Користувач має пости";
}

// Перевірка чи зв'язок порожній
if ($user->posts()->doesntExist()) {
    echo "Пости не знайдено";
}

// Рівень запиту
if (Post::where('published', true)->exists()) {
    // Принаймні один опублікований пост існує
}

// Коли справді потрібна кількість
$postCount = $user->posts()->count();
echo "Користувач має {$postCount} постів";

// Перевірка порожнього на завантаженому зв'язку
if ($user->posts->isEmpty()) {
    // Вже завантажено, без додаткових запитів
}
Tips 23 березня 2026

limit() - не завантажувати непотрібне

При завантаженні 50,000 записів для показу 10 на екрані.

Додаток зависає. Серверу бракує пам'яті. Користувач закриває браузер через 30 секунд.

Проблема:

Без limit(), Eloquent завантажує все в пам'ять. Пагінація допомагає, але все одно потрібен limit() в багатьох випадках.

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

  • Попередні перегляди та зразки
  • Останні N елементів
  • Топ виконавці
  • Будь-який сценарій "показати перші декілька"

Порада: Поєднуй з orderBy() для консистентних результатів. Без сортування limit() повертає випадкову підмножину.

// ПОГАНО: Завантажує все
$products = Product::where('active', true)->get();
// Повертає 50,000 продуктів в пам'яті

// ДОБРЕ: Тільки те що потрібно
$featured = Product::where('featured', true)
    ->orderBy('created_at', 'desc')
    ->limit(5)
    ->get();

// Останні 10 замовлень
$recent = Order::latest()->limit(10)->get();

// Топ 3 користувачі за балами
$leaders = User::orderBy('points', 'desc')->limit(3)->get();

// Попередній перегляд дашборду
$stats = [
    'recent_orders' => Order::latest()->limit(5)->get(),
    'top_products' => Product::orderBy('sales', 'desc')
        ->limit(10)->get(),
    'new_users' => User::latest()->limit(20)->get(),
];

// Без orderBy - непередбачувані результати
$random = Post::limit(5)->get(); // ПОГАНО
$latest = Post::latest()->limit(5)->get(); // ДОБРЕ