Консольное приложение
=====================

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

Структура консольных приложений очень похожа на структуру веб приложения. Она состоит из одного и более классов
[[yii\console\Controller]], которые часто называют командами в консольной среде. Каждый контроллер может иметь одно
или более действий, как и веб контроллеры.

В обоих шаблонах проектов уже есть консольное приложение.
Вы можете запустить его, вызвав скрипт yii, который находится в основной директории вашего приложения.
Вы получите список доступных команд, если вызовете его без параметров:

![Запуск команды ./yii для вывода помощи](images/tutorial-console-help.png)

Как вы можете видеть на скриншоте, в Yii уже определён набор доступных по умолчанию команд:

- [[yii\console\controllers\AssetController|AssetController]] - Позволяет вам объединять и сжимать ваши JavaScript и CSS файлы.
  Больше об этой команде вы можете узнать в [Assets Section](structure-assets.md#using-asset-bundles).
- [[yii\console\controllers\CacheController|CacheController]] - Позволяет вам сбрасывать кеш приложения.
- [[yii\console\controllers\FixtureController|FixtureController]] - Управляет загрузкой и выгрузкой данных фикстур для тестирования.
  Данная команда более подробно описана в [Testing Section about Fixtures](test-fixtures.md#managing-fixtures).
- [[yii\console\controllers\HelpController|HelpController]] - Обеспечивает справочную информацию о консольных командах,
  это команда по умолчанию и она печатает текст, который вы видели выше.
- [[yii\console\controllers\MessageController|MessageController]] - Извлекает сообщения для перевода из файлов с исходными тестами.
  Больше об этой команде вы можете узнать в [I18N Section](tutorial-i18n.md#message-command).
- [[yii\console\controllers\MigrateController|MigrateController]] - Управление миграциями приложения.
  Миграции базы данных более детально описаны в [Database Migration Section](db-migrations.md).
- [[yii\console\controllers\ServeController|ServeController]] - Позволяет запускать встроенный вебсервер PHP.


Использование <span id="usage"></span>
-------------

Вы можете запустить действие консольного контроллера, используя следующий синтаксис:

```
yii <route> [--option1=value1 --option2=value2 ... argument1 argument2 ...]
```

В приведённом выше примере, `<route>` относится к действию контроллера. Параметры будут подставляться в свойства
класса и в аргументы метода действия.

Для примера, [[yii\console\controllers\MigrateController::actionUp()|MigrateController::actionUp()]]
с [[yii\console\controllers\MigrateController::$migrationTable|MigrateController::$migrationTable]] установкой `migrations`
и лимитом в 5 миграций может быть вызвано следующим образом:

```
yii migrate/up 5 --migrationTable=migrations
```

> Note: При использовании в консоли `*`, не забудьте поместить её в кавычки `"*"` чтобы избежать её интерпретации
> и замены на все имена файлов в данной директории.


Входной скрипт <span id="entry-script"></span>
--------------

Входной скрипт консольного приложения - это подобие файла `index.php`, используемого в веб приложении.
Входной скрипт консоли, как правило, называется `yii` и располагается в основной директории приложения.
Он содержит код похожий на следующее:

```php
#!/usr/bin/env php
<?php
/**
 * Yii console bootstrap file.
 */

defined('YII_DEBUG') or define('YII_DEBUG', true);
defined('YII_ENV') or define('YII_ENV', 'dev');

require __DIR__ . '/vendor/autoload.php';
require __DIR__ . '/vendor/yiisoft/yii2/Yii.php';

$config = require __DIR__ . '/config/console.php';

$application = new yii\console\Application($config);
$exitCode = $application->run();
exit($exitCode);
```

Этот скрипт будет создан как часть вашего приложения; вы можете его редактировать, если вам это необходимо.
`YII_DEBUG` можете установить в `false` если вам не нужно видеть отладочный вывод при ошибке, и/или если вы хотите
улучшить общую производительность. В обоих шаблонах приложения, во входном скрипте приложения отладка включена по
умолчанию для обеспечения более дружественного к разработчику окружения.


Настройка <span id="configuration"></span>
---------

Как видно из приведённого выше кода, консольное приложение использует свой собственный файл конфигурации, названый `console.php`.
В этом файле вы должны произвести настройку различных [компонентов приложения](structure-application-components.md) и
свойств консольного приложения.

Если ваше веб и консольное приложение имеет много общих параметров конфигурации, вы можете выделить общую часть в 
отдельный файл, и включить его в оба файла конфигурации (веб и консоль).
Вы можете посмотреть пример в "продвинутом" шаблоне проекта.

> Tip: Иногда, вам может потребоваться запустить консольную команду используя конфигурацию, отличную от той, что
> указано во входном скрипте. Для примера, вы можете использовать команду `yii migrate` для обновления тестовой
> базы данных, которая настраивается для каждого отдельного набора тестов. Для изменения файла конфигурации,
> просто укажите свой конфигурационный файл через опцию `appconfig` при запуске команды:
> 
> ```
> yii <route> --appconfig=path/to/config.php ...
> ```

Автодополнение консольных команд <span id="console-command-completion"></span>
---------------

Автодополнение аргументов команд является полезной возможностью при работе в командной строке.
Начиная с версии 2.0.11, команда `./yii` поддерживает автодополнение для Bash и ZSH. 

### Автодополнение для Bash

Убедитесь, что средства автодополнения для Bash установлены. В большинстве дистрибутивов они поставляются по умолчанию.

Сохраните скрипт для автодополнения в директорию `/etc/bash_completion.d/`:

     curl -L https://raw.githubusercontent.com/yiisoft/yii2/master/contrib/completion/bash/yii -o /etc/bash_completion.d/yii

Для временного использования, вы можете сохранить файл в произвольную директорию и подключить его на время работы сессии,
вызвав команду `source yii`.

Если скрипт был установлен глобально, вам потребуется перезапустить терминал или выполнить команду `source ~/.bashrc` 
для активации автодополнения.

Обратитесь к [инструкции по автодополнению в Bash](https://www.gnu.org/software/bash/manual/html_node/Programmable-Completion.html)
чтобы узнать о других способах подключения скриптов автодополнения в ваше окружение.

### Автодополнение для ZSH

Сохраните скрипт автодополнения в директорию для скриптов автодополнения. Например, `~/.zsh/completion/`

```
mkdir -p ~/.zsh/completion
curl -L https://raw.githubusercontent.com/yiisoft/yii2/master/contrib/completion/zsh/_yii -o ~/.zsh/completion/_yii
```

Добавьте эту директорию в переменную среды `$fpath`, например добавив в конец `~/.zshrc` следующую строку:

```
fpath=(~/.zsh/completion $fpath)
```

Убедитесь, что программа `compinit` запущена. Если это не так - добавьте в `~/.zshrc` следующие строки:

```
autoload -Uz compinit && compinit -i
```

Затем перезапустите ваш терминал, либо выполните команду

```
exec $SHELL -l
```

Создание ваших собственных команд <span id="create-command"></span>
----------------------------------

### Консольный контроллер и действие

Консольная команда определяется как класс контроллера расширяющий [[yii\console\Controller]]. В классе контроллера,
вы определяете одно или несколько действий, которые соответствуют суб-командам контроллера. В каждом действии
вы пишете код, который реализует соответствующие данной суб-команде задачи.

При запуске команды, вам необходимо указать маршрут к действию. Например, маршрут `migrate/create` вызывает суб-команду,
которая соответствует методу [[yii\console\controllers\MigrateController::actionCreate()|MigrateController::actionCreate()]].
Если маршрут, предложенный при вызове команды, не содержит указания идентификатора действия, будет вызвано действие
по умолчанию (так же как и в веб приложении).

### Опции

Для переопределения [[yii\console\Controller::options()]] метода, вы можете указать опции, которые доступны в консольной
команде (controller/actionID). Метод должен возвращать список публичных атрибутов класса. При запуске команды вы
можете указать значение опций, используя синтаксис `--OptionName=OptionValue`. Это свяжет `OptionValue` с атрибутом
`OptionName` класса контроллера.

Если значение по умолчанию опции - это массив, то при установке этой опции, при выполнении команды, значение будет
преобразовано в массив путём разделения входящей строки по запятым.

### Аргументы

Кроме опций, команда может получать аргументы. Аргументы будут переданы в качестве параметров в метод действия,
соответствующего запрошенной суб-команде. Первый аргумент соответствует первому параметру, второй соответственно второму,
и так далее. Если переданных аргументов при вызове команды будет недостаточно, то параметрам будут назначены по
умолчанию, если они определены. Если значения по умолчанию не определены, и не были переданы, команда завершит
выполнение с ошибкой.

Вы можете использовать указание типа `array`, чтобы указать, что аргумент должен рассматриваться как массив. Массив
будет сгенерирован путём разделения входной строки по запятым.

### Псевдонимы опций

Начиная с версии 2.0.8 в классе консольной команды  доступен метод [[yii\console\Controller::optionAliases()]],
позволяющий добавлять псевдонимы для опций.

Для того, чтобы задать псевдоним, перекройте метод [[yii\console\Controller::optionAliases()]] в вашем контроллере:

```php
namespace app\commands;

use yii\console\Controller;

class HelloController extends Controller
{
    public $message;
    
    public function options($actionID)
    {
        return ['message'];
    }
    
    public function optionAliases()
    {
        return ['m' => 'message'];
    }
    
    public function actionIndex()
    {
        echo $this->message . "\n";
    }
}
```

Теперь для запуска команды можно использовать следующий синтаксис:

```
yii hello -m=hello
```


Следующий пример показывает как описывать аргументы:

```php
class ExampleController extends \yii\console\Controller
{
    // Команда "yii example/create test" вызовет "actionCreate('test')"
    public function actionCreate($name) { ... }

    // Команда "yii example/index city" вызовет "actionIndex('city', 'name')"
    // Команда "yii example/index city id" вызовет "actionIndex('city', 'id')"
    public function actionIndex($category, $order = 'name') { ... }

    // Команда "yii example/add test" вызовет "actionAdd(['test'])"
    // Команда "yii example/add test1,test2" вызовет "actionAdd(['test1', 'test2'])"
    public function actionAdd(array $name) { ... }
}
```


### Код возврата

При разработке консольного приложения принято использовать код возврата. Принято, код `0` означает, что команда выполнилась
удачно. Если команда вернула код больше нуля, то это говорит об ошибке. Номер, который был возвращён при ошибке,
потенциально может быть использован для поиска более детальной информации об ошибке.
Для примера `1` может указывать на неизвестную ошибку, а все коды выше могут быть зарезервированы под специфичные
ошибки: ошибки ввода, повреждённые файлы, и что-то другое.

Для того, чтобы ваша консольная команда возвращала код возврата, просто верните целое число в методе действия контроллера:

```php
public function actionIndex()
{
    if (/* возникла проблема */) {
        echo "Возникла проблема!\n";
        return 1;
    }
    // делаем что-нибудь
    return 0;
}
```

Есть несколько предопределённых констант, которые вы можете использовать:

- [[yii\console\ExitCode::OK|ExitCode::OK]] со значением `0`;
- [[yii\console\ExitCode::UNSPECIFIED_ERROR|ExitCode::UNSPECIFIED_ERROR]] со значением `1`.

Хорошая практика, определять значимые для вашего контроллера константы в случае, если вы используете больше типов ошибок.

### Форматирование и цвета

Консоль Yii поддерживает форматирование вывода, который автоматически деградирует до не форматированного, если это не поддерживается
в терминале, где запускается команда.

Вывод форматированных строк прост. Вот как можно вывести некоторый жирный текст:

```php
$this->stdout("Hello?\n", Console::BOLD);
```

Если вам нужно собрать строку динамически объединяя несколько стилей, лучше использовать
[[yii\helpers\Console::ansiFormat()|ansiFormat()]]:

```php
$name = $this->ansiFormat('Alex', Console::FG_YELLOW);
echo "Hello, my name is $name.";
```
