Команда di
При старте фреймворк обходит проект и находит классы — это самая дорогая часть
запуска. di управляет кешем этого обхода: собирает его заранее,
показывает содержимое и удаляет. Он же собирает прокси для #[Async].
Зачем
Обход проекта читает каждый .php и подключает те, где объявлен класс. На среднем
проекте это десятки миллисекунд и лишние мегабайты в памяти мастер-процесса — из
которого потом форкаются все воркеры.
di build делает эту работу один раз, заранее, и складывает результат в файл.
Приложение при старте читает готовый список вместо обхода диска.
Действия
| Действие | Что делает |
|---|---|
build |
Обходит проект один раз: пишет кеш, генерирует прокси #[Async], проверяет корректность |
clean |
Удаляет кеш и все сгенерированные прокси |
show [шаблон] |
Печатает классы из кеша; шаблон фильтрует по подстроке FQCN |
async [шаблон] |
Печатает методы #[Async] и собран ли для них прокси |
php call di build
php call di clean
php call di show
php call di show Repository # только содержащие "Repository"
php call di asyncbuild перед запуском
Основной сценарий — прогрев в контейнере, до старта приложения. Именно так устроен
образ, который создаёт cfg docker:
if ! su-exec winter php /var/www/html/call di build; then
echo "entrypoint: 'call di build' failed — refusing to start" >&2
exit 1
fi
exec su-exec winter php /var/www/html/call run --port="$PORT"`build` — ещё и проверка
Команда не просто складывает список: она разбирает каждый метод #[Async] и
генерирует для него прокси. Метод, который так проксировать нельзя, роняет сборку —
здесь, с понятным сообщением и кодом выхода 1, а не в проде на первом вызове.
Поэтому её и ставят в entrypoint перед запуском: сломанное приложение даёт одну
внятную строку в docker logs вместо контейнера, падающего по кругу.
Дополнительно build предупреждает, когда класс с методами #[Async] создаётся
через new — прокси тогда не применится. Проверка текстовая, new $class и фабрики
она не видит, поэтому это именно предупреждение: сборку оно не роняет.
Где лежит кеш
По умолчанию — во временном каталоге системы, а не в проекте:
/tmp/flytachi.winter.volatile.<имя-проекта>/di.php список классов
/tmp/flytachi.winter.volatile.<имя-проекта>/async/ прокси #[Async]Точные пути показывает php call help di. Сгенерированный код не попадает в образ
и не переживает перезагрузку машины — это осознанный выбор.
Практическое следствие: чистить storage/ для сброса кеша бесполезно, для этого
есть di clean.
При `DEBUG=true` кеш не используется вовсе
В режиме разработки приложение обходит проект на каждом старте, чтобы новый класс
подхватывался без ручной пересборки. Собранный di build в этом режиме просто
игнорируется.
Если после di build изменения «не видны» — первым делом проверьте DEBUG.
show без кеша
Если кеша нет, show не падает: он выполняет живой обход, печатает результат и
предупреждает, что показанное на диск не записано. Так команда остаётся полезной и
в разработке.
async
php call di asyncПоказывает все методы, помеченные #[Async], и состояние прокси для каждого. Это
способ ответить на вопрос «почему метод выполняется синхронно»: если прокси не
собран, вызов идёт напрямую.
Дальше
- Внедрение зависимостей — что попадает в контейнер
- Асинхронные вызовы —
#[Async]и его прокси - cfg docker — где
di buildстоит в запуске контейнера - Консоль — обзор — все команды