CLI · Winter Console

Консоль — обзор

Всё, что делается вокруг проекта, делается через один файл — call. Он запускает сервер, генерирует классы, накатывает схему, управляет фоновыми компонентами и выполняет ваши собственные скрипты. Один разбор аргументов, один формат вывода, один контейнер.

Вход php callКоманд 13 встроенныхСвои Cmd / CmdCustom

Зачем нужна консоль

Разработке нужен не только цикл «запрос — ответ»: создать компонент, поднять сервер, накатить схему, прогреть кеш, запустить фоновый обработчик, разово выполнить скрипт. Без общего инструмента это набор разрозненных файлов в корне проекта, у каждого свой способ принять аргументы и своё представление о том, как печатать ошибку.

call даёт единый вход: одинаковый разбор аргументов, одинаковый вывод, доступ к контейнеру и к конфигурации приложения — и для встроенных команд, и для ваших.

Как устроен вызов

bash
php call <команда> [подкоманда] [аргументы] [-флаги] [--опции[=значение]]

Разбор раскладывает $argv на три части:

Часть Что это Пример
Аргументы Позиционные значения call make .Usermake, .User
Флаги Односимвольные, слипаются -csrc, s, r
Опции --ключ или --ключ=значение --port=9000, --mvc

Первый аргумент — имя команды; без него выполняется help. Флаги можно писать и раздельно, и слитно: -c -s -r и -csr эквивалентны.

Короткие имена

Четыре команды имеют алиасы:

Алиас Команда
sc script
proc process
dmn daemon
sch schedule

Запуск откуда угодно

Файл call содержит chdir(__DIR__), поэтому команды работают из любого каталога — достаточно указать путь:

bash
php /srv/my-app/call mapping show

Это же делает вызовы из systemd, cron и docker exec предсказуемыми: рабочий каталог значения не имеет.

Команды

Разработка

Команда Что делает
make Создаёт компоненты по шаблонам
run Запускает приложение
mapping Показывает таблицу маршрутов
script Выполняет ваши команды (sc)

Окружение и данные

Команда Что делает
cfg .env, ключ проекта, Docker, автодополнение
db Подключение, миграции, пул соединений
storage Служебные каталоги
di Кеш сканера и прокси #[Async]

Фоновые компоненты

Команда Что делает
process Процессы: запуск, остановка, состояние (proc)
daemon Демоны и их флоты воркеров (dmn)
schedule Планировщик и список задач (sch)

Служебные

Команда Что делает
help Список команд, версии, справка по конкретной команде
complete Внутренняя точка для автодополнения оболочки; вручную не вызывается

Справка

bash
php call                 # то же, что help
php call help            # список команд + версии PHP, ядра и проекта
php call help make       # подробная справка по команде
php call make -h         # то же самое флагом

call help без аргументов печатает ещё и окружение — версию ядра, версию PHP, SAPI и корень проекта. Это первое, что стоит приложить к вопросу «почему у меня не работает».

Автодополнение

bash
php call cfg completion       # напечатать скрипт в stdout
php call cfg completion -i    # установить
php call cfg completion -if   # переустановить поверх

Оболочка определяется по $SHELL. Для zsh файл кладётся в ~/.zsh/completions/_call и в ~/.zshrc дописывается fpath; для bash — в ~/.bash_completion.d/call. После установки дополняются имена команд, подкоманды и — там, где это осмысленно — имена классов проекта.

Своя команда

Класс, наследующий Cmd. Скаффолд — php call make -n .Sync:

main/Command/Sync.php
use Flytachi\Winter\Console\Inc\Cmd;

class Sync extends Cmd
{
  public static string $title = 'sync external data';

  public function handle(): void
  {
      $from = $this->args['options']['from'] ?? 'yesterday';

      self::printInfo("syncing since {$from}");
      // ...
      self::printSuccess('done');
  }

  public static function help(): void
  {
      self::printInfo('call script main.command.Sync --from=2026-01-01');
  }
}
bash
php call sc main.command.Sync --from=2026-01-01
Член класса Роль
handle() Тело команды
static $title Строка в списке call script list
static help() Справка; печатается по -h или --help автоматически
init() Необязательный хук перед handle()

Аргументы приходят в $this->args — теми же тремя частями: arguments, flags, options.

Зависимости

Команда создаётся контейнером, поэтому внедрение работает как везде:

php
class Sync extends Cmd
{
  #[Autowired] private ExchangeService $exchange;
  #[Autowired] private LoggerInterface $logger;

  public function handle(): void
  {
      $this->logger->info('sync started');
      $this->exchange->pull();
  }
}

Cmd или CmdCustom

Cmd CmdCustom
Заголовок в списке $title нет
Обработка -h / --help Автоматическая Нет
Метод help() Обязателен Не нужен
Когда брать Команда, которой будут пользоваться Разовый скрипт

Обе находятся сканером и обе запускаются через call script. Разница только в объёме обязательного оформления — см. script.

Свою команду `call <имя>` не запускает

Именами первого уровня — make, run, db — владеет фреймворк: они резолвятся в классы ядра. Ваши команды живут в вашем пространстве имён и вызываются через call script <путь.Класс> или короткое call sc.

Так имя вашей команды никогда не столкнётся с новой командой фреймворка.

Вывод

Печатать через echo не нужно — у Printer есть готовые формы, и весь вывод консоли выглядит одинаково:

Метод Что даёт
printSuccess() · printError() Успех и блок ошибки со стектрейсом
printInfo() · printWarning() Пометки [i] и [!]
printKeyValue() Выровненная пара «ключ — значение»
printBadge() Строка со статусом справа: OK, EXIST, FAILED
printStep() Прогресс вида [3/12]
printTitle() · printLabel() · printDivider() Заголовок, подзаголовок, разделитель

Исключение, вылетевшее из handle(), перехватывается и печатается через printError() — команда не падает стектрейсом PHP в консоль.

Дальше