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

Tips & Tricks: статті за тегом «Цілісність даних»

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

No results.
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 10 березня 2026

DB::transaction() - захист даних

Переказ $100 між рахунками. Гроші списані з Аліси. Сервер падає. Боб їх ніколи не отримує.

Без транзакцій часткові оновлення пошкодять дані.

Як це працює:

Всі запити виконуються як одна атомарна одиниця. Якщо щось не вдається - все відкочується назад. База даних ніколи не опиняється в неузгодженому стані.

Три способи використання:

  1. Closure (рекомендовано) - автоматичний rollback при винятках
  2. Ручний begin/commit - коли потрібен точний контроль
  3. З повторами - автоматична обробка deadlock

Важливо:

Транзакції працюють тільки з InnoDB таблицями. Тримати їх короткими - вони блокують рядки. Довгі операції блокують інші запити.

Не змішувати виклики зовнішніх API з транзакціями бази даних.

// ПОГАНО: Часткове збереження при помилці
$user = User::create($data);
$profile = Profile::create(['user_id' => $user->id]);
// Якщо це не вдається, користувач існує без профілю

// ДОБРЕ: Все або нічого
DB::transaction(function () use ($data) {
    $user = User::create($data);
    $profile = Profile::create(['user_id' => $user->id]);
    $user->sendWelcomeEmail();
});

// Ручний контроль
DB::beginTransaction();
try {
    $order = Order::create($orderData);
    $payment = Payment::create($paymentData);
    DB::commit();
} catch (\Exception $e) {
    DB::rollBack();
    throw $e;
}

// З повтором при deadlock
DB::transaction(function () {
    // Код
}, 3); // Повторити 3 рази якщо deadlock