На продакшені застосунок кешує конфігурацію, маршрути, події й представлення (php artisan optimize). Пакет, який цього не враховує, працює локально й ламається після деплою.
Що змінюється, коли кеші ввімкнені:
| Кеш | Наслідок для пакета |
|---|---|
config:cache |
mergeConfigFrom пропускається - значення беруться з кешу; env() у коді пакета повертає null |
route:cache |
loadRoutesFrom пропускається; замикання в маршрутах пакета раніше ламали кешування - краще контролери |
event:cache |
слухачі, знайдені автоматично, кешуються; динамічна реєстрація в рантаймі може не потрапити |
view:cache |
компілює представлення, зокрема пакетів, зареєстровані через loadViewsFrom |
Типові помилки пакетів:
env()поза файлом конфігурації пакета - післяconfig:cacheповертаєnull. Усе, що залежить від оточення, має проходити черезconfig/<пакет>.php;- конфігурація, змінена в рантаймі (
config(['invoices.x' => ...])уbootзалежно від запиту) - не потрапляє в кеш і поводиться по-різному з кешем і без; - несеріалізовані значення в конфігурації: замикання чи об'єкти в
config/*.phpламаютьconfig:cache(«Your configuration files are not serializable»). Замість замикання - ім'я класу; - важка робота в
boot: запити до бази чи HTTP при кожному завантаженні застосунку, зокрема в консольних командах і вpackage:discoverпід часcomposer install(коли бази ще може не бути).
Інтеграція з командами застосунку:
public function boot(): void
{
if ($this->app->runningInConsole()) {
// викликаються з optimize / optimize:clear
$this->optimizes(
optimize: 'invoices:cache',
clear: 'invoices:clear',
);
// викликається з php artisan reload (перезапуск довгоживучих процесів)
$this->reloads('invoices:restart-workers');
}
// рядок у php artisan about
AboutCommand::add('Invoices', fn () => [
'Version' => '2.3.0',
'PDF driver' => config('invoices.pdf.driver'),
]);
}
Тоді власний кеш пакета (наприклад, скомпільовані шаблони чи маніфест) створюється й очищується разом зі стандартними кешами, і розробнику не треба пам'ятати окрему команду в скрипті деплою.
Octane і довгоживучі процеси: пакет не має зберігати стан запиту в синглтонах чи статичних властивостях - у воркері Octane він «протікає» між запитами. Для даних запиту - scoped() прив'язки замість singleton().
Тест у CI пакета: прогнати набір тестів ще й після config:cache і route:cache у Testbench - так ловляться помилки, які інакше знайде користувач на продакшені.