Урок 03

Конфиг и кэш роутов: config:cache, route:cache

Что это

Кэш конфигов и роутов — предкомпиляция тяжёлых операций.

Что ускоряет:

  • Bootstrap приложения.
  • Загрузку config-файлов.
  • Регистрацию роутов.
  • Разрешение сервисов.

Что даёт:

  • 30–50% быстрее на bootstrap.
  • Меньше I/O.
  • Меньше CPU.

Правило: обязательно в проде.

Все кэш-команды

php artisan config:cache
php artisan route:cache
php artisan view:cache
php artisan event:cache

Что делают:

  • config — один файл со всеми настройками.
  • route — сериализованные роуты.
  • view — скомпилированные Blade.
  • event — карта событий.

Правило: все четыре — в деплой-скрипт.

config:cache

Что делает:

  • Читает все файлы из config/.
  • Объединяет в один.
  • Пишет в bootstrap/cache/config.php.

Что ускоряет: загрузку конфига.

Что важно:

  • Никаких env() вне config-файлов.
  • Никаких closures в config.
  • Никаких обращений к БД.

Правило: env() — только в config/*.php.

Почему env() — только в config

Проблема:

// routes/web.php
if (env('FEATURE_X')) { /* ... */ }

После config:cache — env() вернёт null.

Решение:

// config/features.php
return [
    'x' => env('FEATURE_X', false),
];

// routes/web.php
if (config('features.x')) { /* ... */ }

Правило: env() никогда не вызывать в рантайме.

config:cache и closures

Проблема:

// config/services.php
return [
    'callback' => fn () => 'x',
];

После config:cache — сериализация упадёт.

Решение: closures — через сервис-провайдеры.

Правило: config — только скалярные данные.

route:cache

Что делает:

  • Регистрирует все роуты.
  • Сериализует в bootstrap/cache/routes-v7.php.

Что ускоряет: регистрацию роутов.

Что важно:

  • Нельзя closures-роуты.
  • Нельзя Route::get('/x', fn () => ...).

Пример, который НЕ кэшируется:

Route::get('/hello', function () {
    return 'Hello';
});

Правильный вариант:

Route::get('/hello', [HelloController::class, 'index']);

Правило: роуты — только через контроллеры.

Дублирующиеся роуты

Проблема: два роута с одним именем.

route:cache упадёт с ошибкой.

Решение: php artisan route:list — найти дубли.

Правило: уникальные имена — обязательно.

route:list

Что показывает:

  • Method.
  • URI.
  • Name.
  • Action.
  • Middleware.

Фильтры:

php artisan route:list --name=admin
php artisan route:list --path=api
php artisan route:list --method=POST

Правило: перед деплоем — прогнать route:list.

view:cache

Что делает:

  • Компилирует все Blade в PHP.
  • Пишет в storage/framework/views/.

Что ускоряет: первый рендер.

Что важно: перезапускать после каждого деплоя с изменениями Blade.

Правило: view:cache — в деплое.

event:cache

Что делает: карта событий и listeners.

Что ускоряет: discovery listeners.

Что важно: при event:cache — никаких динамических listeners.

Правило: listeners — в EventServiceProvider.

Полная очистка

php artisan optimize:clear

Что чистит:

  • config.
  • route.
  • view.
  • event.
  • cache приложения.
  • compiled.

Правило: optimize:clear — одна команда для всего.

optimize

php artisan optimize

Что делает:

  • config:cache.
  • route:cache.
  • view:cache.
  • event:cache.

Правило: optimize — в деплой.

Деплой-скрипт

Порядок:

# 1. Обновить код
git pull origin main

# 2. Зависимости без dev
composer install --no-dev --optimize-autoloader

# 3. Миграции
php artisan migrate --force

# 4. Очистка старого кэша
php artisan optimize:clear

# 5. Сборка нового
php artisan optimize

# 6. Перезапуск очередей
php artisan queue:restart

# 7. Перезагрузка FPM (опционально)
sudo systemctl reload php8.5-fpm

Правило: очистка перед сборкой — обязательно.

Почему clear перед optimize

Проблема: старый config.php может конфликтовать.

Что бывает:

  • Старые значения env.
  • Удалённые ключи.
  • Дубли роутов.

Правило: optimize:clear && optimize — надёжнее.

Когда НЕ кэшировать

В dev:

  • Меняешь config — сразу эффект.
  • Правишь роут — сразу.

Что делать:

php artisan optimize:clear

Правило: в dev — без кэша, если активно правишь.

Envoy / Deployer

Envoy (Envoy.blade.php):

@task('deploy', ['on' => 'web'])
    cd /var/www/skills/api
    php artisan down
    git pull origin main
    composer install --no-dev --optimize-autoloader
    php artisan migrate --force
    php artisan optimize:clear
    php artisan optimize
    php artisan queue:restart
    php artisan up
@endtask

Правило: деплой — одна команда.

Проверка

Что должно быть:

  • bootstrap/cache/config.php — существует.
  • bootstrap/cache/routes-v7.php — существует.
  • php artisan route:list — работает.
  • config('app.env') — верный.

Что не должно быть:

  • Ошибок при optimize.
  • Env-зависимых мест вне config.
  • Closures в роутах.

Правило: проверить после каждого деплоя.

Метрика: bootstrap time

Как измерить:

$start = microtime(true);
require __DIR__ . '/../vendor/autoload.php';
$app = require_once __DIR__ . '/../bootstrap/app.php';
$kernel = $app->make(Illuminate\Contracts\Http\Kernel::class);
$kernel->handle($request = Illuminate\Http\Request::capture());
fwrite(STDERR, sprintf("Bootstrap: %.2f ms\n", (microtime(true) - $start) * 1000));

Что даёт: видно эффект от optimize.

Правило: bootstrap < 20 мс — цель.

Composer autoload

Что важно:

composer dump-autoload -o
composer dump-autoload --classmap-authoritative

Что даёт:

  • -o — classmap.
  • --classmap-authoritative — не смотрит в файлы.

Правило: в проде — -o обязательно.

Практика

1. Прогоните optimize.

2. Проверьте bootstrap/cache/.

3. Прогоните route:list.

4. Настройте деплой-скрипт.

5. Убедитесь: env() вне config — нет.

6. Убедитесь: closures-роутов — нет.

7. Замерьте bootstrap до/после.

8. Добавьте composer dump-autoload -o.

9. Проверьте после следующего деплоя.

10. Настройте Envoy / Deployer.

Частые ошибки

1. env() в рантайме:

null после config:cache

Решение: только в config.

2. Closures в роутах:

route:cache падает

Решение: контроллеры.

3. Closures в config:

config:cache падает

Решение: сервис-провайдеры.

4. Дубли имён роутов:

route:cache падает

Решение: route:list для поиска.

5. optimize без clear:

Старые данные

Решение: clear → optimize.

6. Забыли view:cache:

Первый рендер медленнее

Решение: добавить.

7. composer без -o:

Медленный autoload

Решение: -o в проде.

8. dev с optimize:

Не видно изменений config

Решение: optimize:clear в dev.

Итог

  • config:cache — один файл конфига.
  • route:cache — сериализация роутов.
  • view:cache — Blade.
  • event:cache — listeners.
  • optimize — всё сразу.
  • optimize:clear — очистка.
  • env() — только в config.
  • Closures — не в config и роутах.
  • Деплой: clear → optimize → restart.
  • Bootstrap < 20 мс.

Дальше — кэш запросов к БД: Cache::remember().