Консольные приложения ===================== Консольные приложения главным образом используются для выполнения вторичных или фоновых задач, таких как генерация кода, компиляция поискового индекса, отправка сообщений электронной почты и т.д. Yii предоставляет инструмент для разработки консольных приложений, придерживаясь объектно-ориентированного подхода. Он позволяет консольному приложению получить доступ к ресурсам, которые использует основное веб-приложение (например, к базе данных). Обзор ----- Каждая консольная задача представлена в Yii как [команда|CConsoleCommand]. Консольная команда описывается в классе, наследуемом от [CConsoleCommand]. После использования `yiic webapp` для создания начального прототипа приложения, в `protected` будут два файла: * `yiic` — скрипт для Linux/Unix; * `yiic.bat` — скрипт для Windows. В консоли можно ввести следующие команды: ~~~ cd protected yiic help ~~~ После ввода будет отображён список всех доступных на данный момент команд. По умолчанию это команды, предоставляемые Yii (так называемые **системные команды**) и команды, разработанные для конкретных приложений (так называемые **пользовательские команды**). Для получения справки по команде можно запустить ~~~ yiic help <имя-команды> ~~~ Для запуска команды используется следующий формат: ~~~ yiic <имя-команды> [параметры…] ~~~ Создание команд --------------- Консольные команды находятся в файлах с классами в папке, указанной в [CConsoleApplication::commandPath]. По умолчанию это `protected/commands`. Класс консольной команды должен быть унаследован от [CConsoleCommand]. Имя класса должно быть вида `XyzCommand`, где `Xyz` соответствует имени команды, первая буква которого приведена к верхнему регистру. К примеру, команда `sitemap` должна использовать класс `SitemapCommand`. Имена консольных команд регистрозависимы. > Tip|Подсказка: Конфигурируя [CConsoleApplication::commandMap], можно при желании изменить порядок именования и расположения классов команд. Для создания новой команды необходимо либо реализовать метод [CConsoleCommand::run()], либо одно или несколько действий (будут описаны далее). При вводе консольной команды приложение запускает метод [CConsoleCommand::run()]. Параметры метода передаются в соответствии с следующим заголовком: ~~~ [php] public function run($args) { ... } ~~~ где `$args` — дополнительные параметры, переданные из командной строки. Внутри консольной команды для получения доступа к экземпляру консольного приложения можно использовать `Yii::app()`. Через полученный экземпляр можно обращаться к различным компонентам, таким как соединение с базой данных (`Yii::app()->db`). Насколько можно судить, это очень похоже на обычное веб-приложение. > Info|Информация: Начиная с версии 1.1.1 можно создавать глобальные команды, которые используются ***всеми*** приложениями. Для этого определяется переменная окружения `YII_CONSOLE_COMMANDS` и в её значение записывается путь к директории с классами глобальных консольных команд. Действие консольной команды --------------------------- > Note|Примечание: Данная возможность доступна начиная с версии 1.1.5. Часто в консольной команде требуется работать с различными параметрами. Часть из них могут быть обязательными, а часть нет. Также может потребоваться реализовать субкоманды для выполнения различных подзадач. Всё это упрощается при использовании действий. Действие консольной команды — метод в её классе. Имя метода должно быть вида `actionXyz`, где `Xyz` соответствует имени действия и первой буквой, приведённой к верхнему регистру. К примеру, метод `actionIndex` задаёт действие с именем `index`. Для того, чтобы запустить определённое действие, используется следующий формат команды: ~~~ yiic <имя-команды> <имя-действия> --параметр1=значение1 --параметр2=значение2 ... ~~~ Дополнительные пары имя-значение передаются методу действия как именованные параметры. Значение опции `xyz` соответствует параметру `$xyz` метода действия. К примеру, если мы определим следующий класс команды: ~~~ [php] class SitemapCommand extends CConsoleCommand { public function actionIndex($type, $limit=5) { ... } public function actionInit() { ... } } ~~~ То все следующие консольные команды вызовут `actionIndex('News', 5)`: ~~~ yiic sitemap index --type=News --limit=5 // $limit принимает значение по умолчанию yiic sitemap index --type=News // $limit принимает значение по умолчанию. // Так как 'index' — действие по умолчанию, мы можем опустить имя действия. yiic sitemap --type=News // порядок опций не важен yiic sitemap index --limit=5 --type=News ~~~ Если значение опции не указано (то есть `--type` вместо `--type=News`), соответствующему параметру действия будет присвоено значение `true`. > Note|Примечание: Альтернативные форматы указания опций, такие как > `--type News` или `-t News` не поддерживаются. Если объявить параметр как массив, он сможет принять массив значений: ~~~ [php] public function actionIndex(array $types) { ... } ~~~ Чтобы передать массив значений необходимо указать одну и ту же опцию несколько раз: ~~~ yiic sitemap index --types=News --types=Article ~~~ Команда, приведённая выше, запустит `actionIndex(array('News', 'Article'))`. Начиная с версии 1.1.6, Yii позволяет использовать анонимные параметры действий и глобальные опции. Анонимные параметры — это параметры командной строки, не являющиеся опциями. К примеру, в команде `yiic sitemap index --limit=5 News` встречается анонимный параметр со значением `News`. Именованный параметр (опция) `limit` принимает значение, равное 5. Для того, чтобы использовать анонимные параметры, действие должно описать параметр с именем `$args`: ~~~ [php] public function actionIndex($limit=10, $args=array()) {...} ~~~ В массиве `$args` будут содержаться все доступные значения анонимных параметров. Глобальные опции — это параметры командной строки, общие для всех действий команды. К примеру, нам может понадобиться для команды с несколькими действиями завести общую опцию `verbose`. Конечно, можно определить параметр `$verbose` для каждого действия, но лучше задать его **public свойством** класса команды, что автоматически сделает `verbose` глобальной опцией: ~~~ [php] class SitemapCommand extends CConsoleCommand { public $verbose=false; public function actionIndex($type) {...} } ~~~ Приведённый код позволяет использовать опцию `verbose`: ~~~ yiic sitemap index --verbose=1 --type=News ~~~ Код возврата ------------ > Note|Примечание: возможность указать код возврата в консольной команде появилась в версии 1.1.11. При автоматическом запуске консольных команд, например, по cron или используя сервер непрерывной интеграции, важно знать, завершилось ли выполнение команды с ошибкой или успешно. Как раз для этого и предназначены коды возврата. Данные коды являются целочисленными значениями от 0 до 254 (данный интервал задан в [PHP](http://www.php.net/manual/ru/function.exit.php)), где 0 возвращается в случае успеха, а все остальные значения используются для различных ошибок. Как в методе `run()`, так и в действиях команды вы можете вернуть целое число. Оно будет использовано в качестве кода возврата. Пример: ~~~ [php] if (/* ошибка */) { return 1; // выходим с кодом 1 } // … всякая всячина … return 0; // всё хорошо, выходим с кодом 0 ~~~ Если консольная команда ничего не возвращает, приложение завершается с кодом 0. Настройка консольного приложения -------------------------------- По умолчанию, если приложение создаётся с использованием `yiic webapp`, конфигурация консольного приложения находится в `protected/config/console.php`. Как и конфигурация веб-приложения, данный файл является PHP-скриптом, возвращающим массив с начальными значениями экземпляра консольного приложения. То есть в данном файле можно задать любое public свойство [CConsoleApplication]. Так как консольные команды часто создаются для поддержки веб-приложения, требуется использовать те же ресурсы (такие, как соединения с БД), что используются в веб-приложении. Это можно сделать настроив соответствующие компоненты в конфигурации консольного приложения: ~~~ [php] return array( ...... 'components'=>array( 'db'=>array( ...... ), ), ); ~~~ Формат конфигурации очень похож на тот, что используется в веб-приложении, так как и [CConsoleApplication] и [CWebApplication] наследуют один и тот же базовый класс.