Увійти Реєстрація
Блог Серії
Кар'єра
Вакансії Компанії
Навчання
Документація Співбесіди Тестування Відео
Екосистема
Пакети Ресурси Проєкти
Інше
Події Про нас
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 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();
Tips 27 липня 2026

touch() - автооновлення timestamps у батьків

Додали коментар до поста, а updated_at у поста не змінився. Кеш не оновився.

touch() дозволяє автоматично оновлювати час оновлення батьківської моделі.

Як працює:

У дочірній моделі вказуємо $touches. Коли вона зберігається - оновлюється updated_at у батьків.

Де корисно:

  • Інвалідація кешу за timestamp
  • "Остання активність"
  • Відстеження змін контенту

Працює з будь-якими зв'язками.

class Comment extends Model
{
  // Авто-touch для поста
  protected $touches = ['post'];

  public function post()
  {
    return $this->belongsTo(Post::class);
  }
}

// Тепер при створенні/оновленні коментаря
$comment = new Comment(['body' => 'Great post!']);
$comment->post()->associate($post);
$comment->save();
// updated_at у Post буде оновлено

// Ручне оновлення timestamps
$post->touch();

// Touch кількох зв'язків
class Comment extends Model
{
  protected $touches = ['post', 'author'];
}
Tips 24 липня 2026

whereBelongsTo() - чисті запити по зв'язках

Фільтруєте за зв'язком через where('user_id', $user->id)? Можна краще.

whereBelongsTo() сам підставляє зовнішній ключ.

Переваги:

  • Не треба пам'ятати назву foreign key
  • Працює з кастомним ключем
  • Краще читається
  • Безпечніше при рефакторингу

Бонус: працює з масивом моделей.

Порада: дуже зручно в policy-методах, де фільтруєте по auth()->user().

// ПОГАНО: ручний foreign key
$posts = Post::where('user_id', $user->id)->get();
$comments = Comment::where('post_id', $post->id)->get();

// ДОБРЕ: Laravel сам визначає ключ
$posts = Post::whereBelongsTo($user)->get();
$comments = Comment::whereBelongsTo($post)->get();

// Кілька зв'язків
$comments = Comment::whereBelongsTo($user)
  ->whereBelongsTo($post)
  ->get();

// Кастомна назва зв'язку
$posts = Post::whereBelongsTo($user, 'author')->get();

// У policy - максимально чисто
public function update(User $user, Post $post)
{
  return Post::whereBelongsTo($user)->exists();
}
Завантаження...