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

Laravel Context: прихована інформація, яка супроводжує ваш код

Працюючи з Laravel, ми зазвичай передаємо дані явно:

$user = auth()->user();
UserExampleService::process($user);

Або додаємо інформацію безпосередньо до запису логу:

Log::info('Processing order', [
  'order_id' => $order->id,
]);

А що робити, коли деяка інформація має бути доступна протягом усього поточного виконання?

Наприклад:

  • trace ID;
  • поточний URL;
  • ідентифікатор орендаря (tenant ID);
  • назва операції;
  • інформація, потрібна для логування;
  • інформація, яка має переходити в завдання черги.

Саме тут стає цікавою можливість Laravel під назвою Context.

Що таке Laravel Context?

Laravel Context - це місце для інформації, яка належить до поточного виконання вашого застосунку.

Ви додаєте дані:

use Illuminate\Support\Facades\Context;

Context::add('trace_id', 'abc-123');

І отримуєте їх в іншому місці:

$traceId = Context::get('trace_id');

Найцікавіше те, що вам не доводиться передавати $traceId через кожен метод.

Інформація живе в поточному контексті, і нею можуть користуватися інші частини застосунку.

Сам Laravel описує Context як спосіб збирати, отримувати й поширювати інформацію в межах запитів, завдань і команд. До того ж ця інформація інтегрована з логами застосунку.

Найпростіший приклад

Уявімо middleware, що генерує trace ID для кожного запиту:

use Illuminate\Support\Facades\Context;
use Illuminate\Support\Str;

Context::add('trace_id', Str::uuid()->toString());

А тепер десь глибоко в застосунку:

$traceId = Context::get('trace_id');
  • Жодного параметра в контролері.
  • Жодного параметра в сервісі.
  • Жодної глобальної змінної.

Дані просто є частиною поточного контексту.

Справді корисне: логування

Context стає особливо корисним у поєднанні з логуванням.

Наприклад:

Context::add([
  'trace_id' => Str::uuid()->toString(),
  'url' => $request->url(),
]);

А потім:

Log::info('User authenticated', [
  'user_id' => $user->id,
]);

Запис логу може містити і дані, передані в лог явно, і дані, збережені в Context:

User authenticated
{
  "user_id": 27,
  "trace_id": "e04e1a11-...",
  "url": "https://dev.to/login"
}

У документації Laravel 13 дані контексту не зливаються з даними запису в один масив, а додаються окремим блоком метаданих, щоб їх можна було відрізнити: User authenticated. {"auth_id":27} {"url":"https://example.com/login","trace_id":"e04e1a11-..."}.

Це зручно: ви задаєте інформацію один раз, і вона супроводжує всі наступні записи логу, замість того щоб додавати її вручну скрізь.

А ось тут Context стає по-справжньому цікавим

Уявімо, що відбувається таке:

HTTP-запит
  │
  ├── Контролер
  │     │
  │     └── Сервіс
  │           │
  │           ├── контекст
  │           └── Dispatch завдання
  │
  ▼
Дані завдання (контекст зібрано, дегідратовано й збережено в даних)
  │
  ▼
Черга
  │
  ▼
Воркер
  │
  ▼ гідратація -> відновлення контексту
  │
  ▼
Виконання завдання

Зазвичай HTTP-запит і завдання в черзі - це два різні виконання.

Тож звідки завданню знати про контекст, створений під час початкового запиту?

Laravel бере це на себе: коли завдання відправляється в чергу, Laravel збирає поточний контекст і зберігає його разом із даними завдання.

Коли воркер починає обробляти завдання, цей контекст відновлюється в поточному виконанні. Laravel називає ці два етапи дегідратацією (dehydrating) і гідратацією (hydrating).

Тож ось це:

Context::add('trace_id', 'abc-123');

ProcessPodcast::dispatch($podcast);

може привести до того, що завдання побачить:

Context::get('trace_id');
// "abc-123"

А отже:

Log::info('Processing podcast');

все ще міститиме початкову інформацію для трасування. Це напрочуд потужна можливість для налагодження розподілених процесів.

Тобто Context - не глобальна змінна, спільна для кількох процесів.

Найцікавіше

Воркер черги в Laravel - це довготривалий процес: він обробляє одне завдання, потім інше:

Воркер
  │
  ├── Завдання A
  │
  ├── Завдання B
  │
  ├── Завдання C
  │
  └── Завдання D

Якби Context просто зберігався глобально й ніколи не очищувався, могло б вийти таке:

Завдання A
trace_id = abc-123

Завдання B
trace_id = abc-123  (а це погано)

Тому Laravel керує життєвим циклом навколо воркера (registerWorker()). Логіка скидання воркера в сервіс-провайдері черги серед інших операцій очищення скидає спільний контекст логування й очищає scoped-екземпляри між завданнями.

Контекст може бути прихованим

Не все, що ви кладете в Context, має з'являтися в логах. Саме для цього Laravel має прихований контекст:

Context::addHidden('internal_hidden_id', 123);

Context::getHidden('internal_hidden_id');
// 123

Але:

Context::get('internal_hidden_id');
// null

Прихований контекст не додається до записів логу й має окремий API.

Отже, маємо два види контексту:

Context
├── Звичайні дані
│   └── Можуть потрапляти в логи
│
└── Приховані дані
    └── Доступні застосунку, але не потрапляють у логи

Це розрізнення особливо корисне, коли контекст містить внутрішню інформацію, якій не місце в логах застосунку.

Сам Laravel теж користується прихованим контекстом.

У CallQueuedHandler Laravel може зберігати таку інформацію:

laravel_unique_job_cache_store
laravel_unique_job_key
laravel_unique_job_lock_owner

Навіщо? Буває, що Laravel не може десеріалізувати завдання з черги, бо модель, на яку воно посилається, відсутня.

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

Обробник бере ці значення з прихованого контексту й використовує їх, щоб відновити або зняти блокування.

У контексту може бути життєвий цикл

Laravel також дає змогу втрутитися в момент, коли контекст перетинає межу черги.

Зазвичай колбеки dehydrating і hydrated реєструють у методі boot класу AppServiceProvider вашого застосунку.

Наприклад:

Context::dehydrating(function (Repository $context) {
  // Підготувати контекст, перш ніж його буде прикріплено до завдання
  $context->addHidden('locale', Config::get('app.locale'));
});

І:

Context::hydrated(function (Repository $context) {
  // Відновити або використати контекст, коли завдання стартує
  if ($context->hasHidden('locale')) {
    Config::set('app.locale', $context->getHidden('locale'));
  }
});

Тобто Context - це не просто статичний масив, що десь лежить.

Laravel дає вам хуки навколо переходу з одного середовища виконання в інше.

Одна важлива деталь із документації Laravel: усередині цих колбеків слід змінювати репозиторій $context, переданий у колбек, а не викликати сам фасад Context.

Context - це більше, ніж сховище ключ-значення

Окрім add() і get(), є й інші корисні можливості.

Наприклад, можна зберігати стек:

Context::push('breadcrumbs', 'checkout');
Context::push('breadcrumbs', 'payment');

Context::get('breadcrumbs');

Можна отримати значення й одразу його видалити:

$value = Context::pull('key');

Або запам'ятати значення, лише якщо його ще немає:

$permissions = Context::remember(
  'user-permissions',
  fn () => $user->permissions,
);

Laravel також має has, missing, forget, only, except і відповідні методи для прихованого контексту.

Усе це не знадобиться вам щодня. Головне - розуміти, для чого Context призначений.

Коли ним користуватися?

Context особливо доречний, коли інформація належить до потоку виконання, а не до конкретної функції.

Наприклад:

Запит
  │
  ├── Middleware
  │
  ├── Контролер
  │
  ├── Сервіс
  │
  ├── Подія
  │
  ├── Завдання черги
  │
  └── Логи

Значення на кшталт:

trace_id = abc-123

описує всю операцію, а не один конкретний метод. Саме тут Context і розкривається: замість того щоб скрізь писати

processOrder($order, $traceId);

можна тримати інформацію для трасування в Context:

Context::get('trace_id');

і дозволити фреймворку переносити її крізь увесь потік виконання.

Одне важливе правило

Context не замінює звичайних даних застосунку, тож не кладіть у нього все підряд. Корисна ментальна модель:

Аргументи описують, що потрібно функції. Контекст описує, що відбувається навколо поточного виконання.

Наприклад:

processOrder($order);

має сенс, бо $order - це вхідні дані операції.

Але й:

Context::add('trace_id', $traceId);

має сенс, бо trace ID описує виконання, в межах якого відбувається ця операція.

То зрештою це ще одне сховище ключ-значення?

Сам API простий:

Context::add(...)
Context::get(...)

Цікаве те, що Laravel робить із цією інформацією.

Він може:

  • додавати її до логів;
  • переносити її з HTTP-запиту в завдання черги;
  • відновлювати її, коли завдання стартує;
  • тримати приховані дані окремо від даних для логів;
  • давати застосунку хуки навколо цього перенесення.

Тож наступного разу, коли побачите:

Context::add('trace_id', $traceId);

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

Джерело: документація Laravel про Context.

Переклад оригіналу: dev.to
14

Читати в документації

Коментарі

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

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

Читайте також

Переклади 27 жовтня 2026

Коли повторні спроби лише шкодять: як захистити систему від перевантаження

Венделл Адріел розбирає, як повторні спроби перетворюють повільну залежність на відмову всього застосунку, і як від цього захиститися: дедлайн на всю операцію, ліміт конкурентності, бюджет повторних спроб, backoff з jitter і один власник рішень про повтори.

16
Створюй → тестуй → виправляй → повторюй: автоматизація розробки на Laravel за допомогою AI-агентів
Переклади 05 жовтня 2026

Створюй → тестуй → виправляй → повторюй: автоматизація розробки на Laravel за допомогою AI-агентів

Як перестати бути кур'єром між AI і терміналом: будуємо автоматичний цикл build → test → fix на Laravel Boost, OpenCode CLI та Laravel Queue, із лімітом спроб і фінальним рев'ю людиною.

3

Вакансії за темою

Senior PHP Developer / Software Architect

Senior PHP-розробник та архітектор для розвитку й модернізації платформи публічних закупівель з фінансовими процесами та інтеграціями. Роль поєднує проєктування складних backend-систем, рефакторинг legacy-компонентів і безпосередню розробку на PHP 8+ із Symfony або Laravel. Ключові вимоги: 10+ років PHP-розробки, 5+ років у FinTech, активне використання AI-інструментів у розробці, досвід REST API, Redis/RabbitMQ, Docker і CI/CD.

EpicentrK Нова
2 дні тому

Backend PHP Developer (Middle+/Senior)

Розробник бекенду на PHP, який інтегрує внутрішні та зовнішні системи, проєктує й оптимізує складні SQL-запити та бере участь у плануванні архітектури сервісів. Потрібен досвід комерційної розробки на PHP 7.x/8.x від 4 років, робота з Symfony та/або Laravel, REST API, PostgreSQL/MySQL, MongoDB/Redis, RabbitMQ та Elasticsearch, а також глибоке знання OOP, SOLID і проєктування індексів.

EpicentrK Нова
2 дні тому

PHP Backend Developer (Middle+ / Senior)

Розробка та підтримка backend-сервісів на PHP: новий функціонал, REST API, інтеграції зі сторонніми сервісами, фонові завдання та черги. Ключовий фокус на PostgreSQL: проєктування схем, оптимізація складних SQL-запитів і індексів, аналіз продуктивності через EXPLAIN ANALYZE. Вимоги: від 4 років комерційного досвіду з PHP 8.x, фреймворки Laravel, Symfony або Yii2, робота зі складною бізнес-логікою, тести та Code Review.

Пакети за темою

Kalimera

welldigit/kalimera

Interactive installer that scaffolds Laravel applications the Well Digit way.

v1.0.0 16

Bagisto

bagisto/bagisto

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

28,284 v2.5.0 13 26