Консольные команды в Yii 2: как написать первую с первого раза
Разбираем, как создать рабочую консольную команду в Yii 2: где лежит контроллер, как принять аргументы и опции, как запустить по расписанию и не наступить на типичные грабли.

К концу этого гайда у вас будет рабочая консольная команда в Yii 2, которую можно запустить руками и повесить в cron. На всё уйдёт минут двадцать, если проект уже развёрнут. Мы напишем команду очистки устаревших записей, научим её принимать аргумент и опцию и разберём ошибки, которые видят почти все, кто делает это впервые.
Речь про Yii 2 (ветка 2.0.x — актуальная стабильная на момент написания). В Yii 3 подход к консоли другой, здесь он не рассматривается. Если у вас advanced-шаблон, а не basic, отличается только путь к папке — об этом ниже.
Что нужно иметь до начала
- Развёрнутый проект на Yii 2 (basic или advanced), который открывается в браузере;
- PHP доступен из командной строки: проверьте
php -v; - Права на запись в папку с контроллерами консоли;
- Понимание, где лежит входной файл
yii— в корне проекта (basic) или в корне (advanced, тоже в корне).
Проверьте, что консоль вообще запускается. Из корня проекта выполните:
php yii
Должен вывестись список доступных команд с описаниями. Если вместо этого сыплются ошибки подключения к базе — консольное приложение читает свой конфиг, и до него мы ещё дойдём. Список команд появился — идём дальше.
Шаг 1. Создаём контроллер команды
Консольная команда в Yii 2 — это класс-контроллер, унаследованный от yii\console\Controller. Каждый публичный метод с префиксом action становится отдельным действием (action).
Создайте файл. В basic-шаблоне это commands/CleanupController.php, в advanced — console/controllers/CleanupController.php.
<?php
// basic: commands/CleanupController.php
namespace app\commands;
use yii\console\Controller;
use yii\console\ExitCode;
class CleanupController extends Controller
{
// Действие по умолчанию: php yii cleanup
public function actionIndex()
{
$this->stdout("Команда cleanup работает\n");
return ExitCode::OK;
}
}
Обратите внимание на namespace. В basic он app\commands, в advanced — console\controllers. Namespace должен совпадать с тем, что прописан в конфиге консоли (controllerNamespace), иначе Yii команду не найдёт.
Проверка: выполните php yii cleanup. В консоли должно появиться «Команда cleanup работает». Если появилось — контроллер найден и подключён.
Шаг 2. Добавляем аргумент
Аргументы действия — это параметры метода. Yii автоматически сопоставит их с позиционными значениями из командной строки.
public function actionOld($days)
{
$days = (int) $days;
$this->stdout("Удаляю записи старше {$days} дней\n");
// здесь была бы логика удаления
return ExitCode::OK;
}
Запуск:
php yii cleanup/old 30
Значение 30 попадёт в $days. Если аргумент обязательный и его не передать, Yii сам выведет ошибку «Missing required arguments» — придумывать проверку не нужно. Хотите значение по умолчанию — задайте его в сигнатуре: actionOld($days = 30).
Аргумент — это позиция, опция — это имя.php yii cleanup/old 30— 30 это аргумент.php yii cleanup/old --days=30так не сработает, пока вы не объявите опцию явно. Путать эти два механизма — источник половины «почему не передаётся значение».
Шаг 3. Добавляем опцию
Опции (флаги с именем, вроде --dry-run) объявляются через свойство класса плюс метод options(). Одним свойством дело не обойдётся — Yii не подхватит его как опцию автоматически.
<?php
namespace app\commands;
use yii\console\Controller;
use yii\console\ExitCode;
class CleanupController extends Controller
{
// Свойство под опцию
public $dryRun = false;
// Регистрируем опцию для действия old
public function options($actionID)
{
return array_merge(parent::options($actionID), [
'dryRun',
]);
}
// Короткий алиас: -d вместо --dryRun
public function optionAliases()
{
return ['d' => 'dryRun'];
}
public function actionOld($days = 30)
{
$days = (int) $days;
if ($this->dryRun) {
$this->stdout("Пробный прогон: ничего не удаляю\n");
return ExitCode::OK;
}
$this->stdout("Удаляю записи старше {$days} дней\n");
return ExitCode::OK;
}
}
Теперь работает всё это:
php yii cleanup/old 30 --dryRun
php yii cleanup/old 30 -d
Проверка: с флагом --dryRun выводится «Пробный прогон», без него — «Удаляю записи». Если флаг игнорируется — вы забыли добавить имя свойства в options().
Шаг 4. Возвращаем правильный код выхода
Это то, что новички пропускают, а cron и CI на это смотрят. Действие должно возвращать целочисленный код: 0 — успех, ненулевой — ошибка. В Yii для этого есть константы yii\console\ExitCode.
public function actionOld($days = 30)
{
if ($days < 1) {
$this->stderr("Число дней должно быть больше нуля\n");
return ExitCode::DATAERR; // ненулевой код -> cron увидит сбой
}
// ... работа
return ExitCode::OK; // это 0
}
Ошибки пишите в stderr, а не в stdout — так их можно отделить в логах. Обычный вывод — в stdout.
Шаг 5. Ставим в cron
Команда готова — теперь запуск по расписанию. Важно: cron стартует без вашего окружения, поэтому указывайте полные пути и, если нужно, окружение Yii.
# Каждую ночь в 3:00, чистим записи старше 30 дней
0 3 * * * /usr/bin/php /var/www/project/yii cleanup/old 30 >> /var/log/cleanup.log 2>&1
Конструкция 2>&1 перенаправляет stderr туда же, куда stdout — иначе ошибки уйдут в письмо от cron и потеряются. Путь к php берите из which php, а не наугад.
Если не получилось
Пять ошибок, которые встречаются чаще всего:
- «Unknown command: cleanup» — namespace класса не совпадает с
controllerNamespaceв конфиге консоли, либо имя файла не оканчивается наController.php, либо класс не совпадает с именем файла. Проверьте все три. - «Class not found» / автозагрузка — после создания файла composer иногда не видит новый класс. Выполните
composer dump-autoload. В basic-шаблоне со стандартным namespace это обычно не нужно, но помогает при кастомных путях. - Опция игнорируется — имя свойства не добавлено в метод
options(). Одного объявленияpublic $dryRunнедостаточно. - «Missing required arguments» — обязательный аргумент действия не передан. Либо передайте его, либо задайте значение по умолчанию в сигнатуре метода.
- В cron работает не так, как в консоли — почти всегда дело в разном окружении: другой пользователь, другой путь к php, не подхватился
.env. Запустите ту же строку из cron вручную под пользователем cron и сравните вывод.
Про конфиг консоли
Консольное приложение читает отдельный конфиг, не тот, что использует веб. В basic это config/console.php, в advanced — console/config/main.php. Если в консоли не находится компонент (например, db или очередь), которого хватает в вебе, — он просто не описан в консольном конфиге. Скопируйте нужный компонент туда.
Здесь же задаётся controllerNamespace — тот самый namespace, который должен совпасть с namespace вашего класса.
Что дальше
Первая команда работает — теперь стоит навести порядок. Длинный вывод оборачивайте в $this->ansiFormat() для цветовой подсветки. Для интерактивных подтверждений в опасных операциях используйте $this->confirm() — он спросит «y/n». Для регулярных фоновых задач присмотритесь к официальному расширению yii2-queue: cron хорош для простого расписания, но очередь надёжнее для отложенных заданий с повторами. Читать дальше — раздел «Console Applications» в руководстве Yii 2.
Аналитик звонков: Разбор записи звонка по этапам сделки: где сорвалось, что упущено, три исправляемые рекомендации с цитатами.
Спросить за 90 ₽Источники: Yii 2 Guide — Console Applications, Yii 2 API — yii\console\Controller
Частые вопросы
У меня advanced-шаблон, а не basic — что менять?
Команда не находится, хотя файл создан. Что проверить?
Почему опция --dryRun не срабатывает, хотя свойство объявлено?
В консоли команда работает, а из cron — нет. В чём дело?
Обязательно ли возвращать код выхода из действия?
Работает ли этот подход в Yii 3?
Материал носит информационный характер и подготовлен редакцией «Агентуры». Он не является офертой, рекламой или индивидуальной консультацией. Упомянутые продукты, компании и торговые знаки принадлежат их правообладателям. Перед принятием решений, влекущих юридические или финансовые последствия, обратитесь к профильному специалисту.