> For the complete documentation index, see [llms.txt](https://delphinpro.gitbook.io/laravel-ru/llms.txt). Markdown versions of documentation pages are available by appending `.md` to page URLs; this page is available as [Markdown](https://delphinpro.gitbook.io/laravel-ru/digging-deeper/artisan.md).

# Консоль Artisan

## Вступление

Artisan — это интерфейс командной строки, входящий в комплект поставки Laravel. Он предоставляет ряд полезных команд, которые могут помочь вам в процессе создания приложения. Для просмотра списка всех доступных команд Artisan можно воспользоваться командой `list`:

```bash
php artisan list
```

Каждая команда также включает в себя экран справки, в котором отображаются и описываются доступные аргументы и опции команды. Для просмотра экрана справки имени команды предшествует `help`:

```
php artisan help migrate
```

### Tinker (REPL)

Laravel Tinker — это мощный REPL для фреймворка Laravel, работающий на основе пакета [PsySH](https://github.com/bobthecow/psysh).

**Установка**

Все приложения Laravel включают Tinker по умолчанию. Однако при необходимости вы можете установить его вручную с помощью Composer:

```bash
composer require laravel/tinker
```

**Использование**

Tinker позволяет взаимодействовать со всем приложением Laravel в командной строке, включая Eloquent ORM, задания, события и многое другое. Чтобы войти в среду Tinker, запустите команду `tinker`:

```bash
php artisan tinker
```

Вы можете опубликовать конфигурационный файл Tinker'а с помощью команды `vendor:published`:

```bash
php artisan vendor:publish --provider="Laravel\Tinker\TinkerServiceProvider"
```

{% hint style="warning" %}
Функция-помощник `dispatch` и метод `dispatch` в классе `Dispatchable` зависит от сборщика мусора для размещения задания в очереди. Поэтому при использовании Tinker для отправки заданий следует использовать `Bus::dispatch` или `Queue::push`.
{% endhint %}

**"Белый список" команд**

Tinker использует белый список для определения того, какие команды Artisan разрешено выполнять в оболочке. По умолчанию вы можете запускать команды `clear-compiled`, `down`, `env`, `inspire`, `migrate`, `optimize` и `up`. Если вы хотите перечислить больше команд, вы можете добавить их в массив `commands` в конфигурационном файле `tinker.php`:

```php
'commands' => [
    // App\Console\Commands\ExampleCommand::class,
],
```

**Классы, которые не должны использовать псевдонимы**

Обычно Tinker автоматически присваивает классам псевдонимы, как это требуется в Tinker. Однако, вы можете никогда не использовать псевдонимы для некоторых классов. Для этого перечислите классы в массиве `dont_alias` конфигурационного файла `tinker.php`:

```php
'dont_alias' => [
    App\User::class,
],
```

## Написание команд

В дополнение к командам, предоставляемым Artisan, вы также можете создавать свои собственные пользовательские команды. Команды обычно хранятся в каталоге `app/Console/Commands`; однако, вы можете выбрать своё собственное место хранения, главное, чтобы ваши команды могли быть загружены Composer\`ом.

### Генерация команд

Для создания новой команды используйте Artisan-команду `make:command`. Эта команда создаст новый класс команды в каталоге `app/Console/Commands`. Не беспокойтесь, если этот каталог не существует в вашем приложении, так как он будет создан при первом запуске команды `make:command`. Сгенерированная команда будет включать набор свойств и методов по умолчанию, которые присутствуют во всех командах:

```bash
php artisan make:command SendEmails
```

### Структура команды

После генерации команды у класса необходимо заполнить свойства `signature` и `description`, которые будут использоваться при отображении Вашей команды на экране `list`. Метод `handle` будет вызван при выполнении Вашей команды. Вы можете поместить логику Вашей команды в этот метод.

{% hint style="info" %}
Для повторного использования кода, это хорошая практика, сохраняйте консольные команды легкими и позвольте им использовать сервисы приложений для выполнения своих задач. В примере ниже, обратите внимание, что мы вводим класс обслуживания, чтобы сделать "тяжелую задачу" отправки электронной почты.
{% endhint %}

Давайте рассмотрим пример команды. Обратите внимание, что мы можем ввести любые необходимые нам зависимости в метод `handle` команды. [Service-контейнер Laravel](/laravel-ru/architecture-concepts/container.md) автоматически внедрит все зависимости, которые указаны в сигнатуре этого метода:

```php
<?php

namespace App\Console\Commands;

use App\DripEmailer;
use App\User;
use Illuminate\Console\Command;

class SendEmails extends Command
{
    /**
     * The name and signature of the console command.
     *
     * @var string
     */
    protected $signature = 'email:send {user}';

    /**
     * The console command description.
     *
     * @var string
     */
    protected $description = 'Send drip e-mails to a user';

    /**
     * Create a new command instance.
     *
     * @return void
     */
    public function __construct()
    {
        parent::__construct();
    }

    /**
     * Execute the console command.
     *
     * @param  \App\DripEmailer  $drip
     * @return mixed
     */
    public function handle(DripEmailer $drip)
    {
        $drip->send(User::find($this->argument('user')));
    }
}
```

### Команды на функциях обратного вызова

Команды, основанные на функциях обратного вызова, представляют собой альтернативу определению консольных команд как классов. Точно так же, как маршрутные Closures являются альтернативой контроллерам, думайте о командах Closures как об альтернативе командным классам. В методе `commands` класс `app/Console/Kernel.php` загружает файл `routes/console.php`:

```php
/**
 * Register the Closure based commands for the application.
 *
 * @return void
 */
protected function commands()
{
    require base_path('routes/console.php');
}
```

Несмотря на то, что этот файл не определяет HTTP-маршруты, он определяет консольные точки входа (routes) в приложение. Внутри этого файла вы можете определить все ваши маршруты, основанные на Closure, используя метод `Artisan::command`. Метод `command` принимает два аргумента: [сигнатура команды](/laravel-ru/digging-deeper/artisan.md#opredelenie-vkhodnykh-dannykh) и Closure, который получает аргументы и опции команд:

```php
Artisan::command('build {project}', function ($project) {
    $this->info("Building {$project}!");
});
```

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

**Type-Hinting Dependencies**

В дополнение к получению аргументов и опций вашей команды, в коллбеке можно также указывать подсказки типов на дополнительные зависимости, которые вы хотели бы разрешить из [сервис-контейнера](/laravel-ru/architecture-concepts/container.md):

```php
use App\DripEmailer;
use App\User;

Artisan::command('email:send {user}', function (DripEmailer $drip, $user) {
    $drip->send(User::find($user));
});
```

**Описание команды, основанной на коллбеке**

При определении команды, основанной на Closure, вы можете использовать метод `decribe` для добавления описания к команде. Это описание будет отображаться при выполнении команд `php artisan list` или `php artisan help`:

```php
Artisan::command('build {project}', function ($project) {
    $this->info("Building {$project}!");
})->describe('Build the project');
```

## Определение входных данных

При написании консольных команд принято собирать входные данные от пользователя через аргументы или опции. Laravel делает очень удобным определение входа, который вы ожидаете от пользователя, используя свойство `signature` в ваших командах. Свойство `signature` позволяет определить имя, аргументы и опции для команды в едином, выразительном синтаксисе.

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

Все аргументы и опции, предоставленные пользователем, обернуты фигурными скобками. В следующем примере команда определяет один **обязательный** аргумент: `user`:

```php
/**
 * The name and signature of the console command.
 *
 * @var string
 */
protected $signature = 'email:send {user}';
```

Вы также можете сделать аргументы необязательными и определить значения по умолчанию:

```php
// Optional argument...
email:send {user?}

// Optional argument with default value...
email:send {user=foo}
```

### Опции

Опции, как и аргументы, являются другой формой пользовательского ввода. Опции префиксуются двумя дефисами (`--`), когда они указываются в командной строке. Существует два типа опций: те, которые получают значение и те, которые не получают. Опции, которые не получают значения, служат булевым "переключателем". Рассмотрим пример такого типа опций:

```php
/**
 * The name and signature of the console command.
 *
 * @var string
 */
protected $signature = 'email:send {user} {--queue}';
```

В этом примере при вызове команды может быть указан переключатель `--queue`. Если передан переключатель `--queue`, то значение опции будет `true`. В противном случае, значение будет `false`:

```bash
php artisan email:send 1 --queue
```

**Опции со значениями**

Далее давайте рассмотрим вариант, который ожидает значение. Если пользователь должен указать значение для опции, добавьте к имени опции знак `=`:

```php
/**
 * The name and signature of the console command.
 *
 * @var string
 */
protected $signature = 'email:send {user} {--queue=}';
```

В этом примере, пользователь может передать значение для опции, подобное этому:

```bash
php artisan email:send 1 --queue=default
```

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

```bash
email:send {user} {--queue=default}
```

**Сокращения для опций**

Чтобы назначить ярлык при определении опции, вы можете указать его перед именем опции и использовать разделитель | для отделения ярлыка от полного имени опции:

```bash
email:send {user} {--Q|queue}
```

### Ввод массивов

Если нужно определить аргументы или опции ожидающие ввода массива, Вы можете использовать символ `*`. Сначала рассмотрим пример, который задает аргумент массива:

```bash
email:send {user*}
```

При вызове этого метода в командную строку могут быть переданы аргументы `user`. Например, следующая команда установит значение `user` в `['foo', 'bar']`:

```bash
php artisan email:send foo bar
```

При определении опции, ожидающей ввода массива, каждое значение опции, передаваемое команде, должно иметь префикс с именем опции:

```bash
email:send {user} {--id=*}

php artisan email:send --id=1 --id=2
```

### Описание аргументов и опций

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

```php
/**
 * The name and signature of the console command.
 *
 * @var string
 */
protected $signature = 'email:send
                        {user : The ID of the user}
                        {--queue= : Whether the job should be queued}';
```

## Ввод-вывод команды

### Получение входных данных

Пока ваша команда выполняется, вам, очевидно, понадобится доступ к значениям аргументов и опций, принятых вашей командой. Для этого вы можете использовать методы `argument` и `option`:

```php
/**
 * Execute the console command.
 *
 * @return mixed
 */
public function handle()
{
    $userId = $this->argument('user');

    //
}
```

Если вам нужно получить все аргументы в виде массива, вызовите метод `arguments`:

```php
$arguments = $this->arguments();
```

Опции могут быть извлечены так же легко, как и аргументы, с помощью метода `option`. Чтобы получить все опции в виде массива, вызовите метод `options`:

```php
// Retrieve a specific option...
$queueName = $this->option('queue');

// Retrieve all options...
$options = $this->options();
```

Если аргумент или опция не существует, то будет возвращено значение `null`.

### Запрос входных данных

В дополнение к отображению вывода, Вы также можете попросить пользователя предоставить ввод во время выполнения Вашей команды. Метод `ask` покажет пользователю заданный вопрос, примет его ввод, а затем вернет ввод пользователя обратно Вашей команде:

```php
/**
 * Execute the console command.
 *
 * @return mixed
 */
public function handle()
{
    $name = $this->ask('What is your name?');
}
```

Метод `secret` похож на `ask`, но ввод данных пользователем не будет виден во время набора в консоли. Этот метод полезен при запросе конфиденциальной информации, такой как пароль:

```php
$password = $this->secret('What is the password?');
```

**Запрос подтверждения**

Если вам нужно запросить у пользователя простое подтверждение, вы можете воспользоваться методом `confirm`. По умолчанию этот метод возвращает `false`. Однако, если пользователь введет `y` или `yes` в ответ на запрос, метод вернет `true`.

```php
if ($this->confirm('Do you wish to continue?')) {
    //
}
```

**Автозавершение**

Метод `anticipate` может быть использован для обеспечения автозавершения возможных вариантов выбора. Пользователь может выбрать любой ответ, независимо от подсказок автозавершения:

```php
$name = $this->anticipate('What is your name?', ['Taylor', 'Dayle']);
```

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

```php
$name = $this->anticipate('What is your name?', function ($input) {
    // Return auto-completion options...
});
```

**Множественный выбор**

Если вам нужно дать пользователю предопределенный набор вариантов, вы можете использовать метод `choice`. Вы можете установить значение индекса массива по умолчанию, которое будет возвращено, если не выбран ни один из вариантов:

```php
$name = $this->choice('What is your name?', ['Taylor', 'Dayle'], $defaultIndex);
```

Кроме того, метод `choice` принимает необязательные четвертый и пятый аргументы для определения максимального количества попыток выбора правильного ответа и допустимости множественного выбора:

```php
$name = $this->choice(
    'What is your name?',
    ['Taylor', 'Dayle'],
    $defaultIndex,
    $maxAttempts = null,
    $allowMultipleSelections = false
);
```

### Вывод в консоль

Для отправки вывода в консоль используйте методы `line`, `info`, `comment`, `question` и `error`. Каждый из этих методов будет использовать соответствующие цвета ANSI. Например, давайте покажем пользователю некоторую общую информацию. Обычно, метод `info` будет отображаться в консоли в виде зеленого текста:

```php
/**
 * Execute the console command.
 *
 * @return mixed
 */
public function handle()
{
    $this->info('Display this on the screen');
}
```

Для отображения сообщения об ошибке используйте метод `error`. Текст сообщения об ошибке обычно отображается красным цветом:

```php
$this->error('Something went wrong!');
```

Если вы хотите отобразить обычный, не цветной консольный вывод, используйте метод `line`:

```php
$this->line('Display this on the screen');
```

**Табличный вывод**

Метод `table` позволяет легко и корректно форматировать несколько строк/столбцов данных. Просто передайте методу заголовки и строки. Ширина и высота будут динамически рассчитываться на основе заданных данных:

```php
$headers = ['Name', 'Email'];

$users = App\User::all(['name', 'email'])->toArray();

$this->table($headers, $users);
```

**Индикатор прогресса**

Для длительных задач может быть полезным отображение индикатора прогресса. Используя объект output, мы можем запускать, продвигать и останавливать индикатор прогресса. Сначала определите общее количество шагов, через которые будет проходить процесс. Затем, после обработки каждого элемента, передвиньте индикатор:

```php
$users = App\User::all();

$bar = $this->output->createProgressBar(count($users));

$bar->start();

foreach ($users as $user) {
    $this->performTask($user);

    $bar->advance();
}

$bar->finish();
```

Для получения более подробной информации о дополнительных опциях обратитесь к документации [компонента Symfony Progress Bar](https://symfony.com/doc/current/components/console/helpers/progressbar.html).

## Регистрация команд

Из-за вызова метода `load` в методе `commands` консольного ядра, все команды в каталоге `app/Console/Commands` будут автоматически зарегистрированы в Artisan. Фактически, Вы можете совершать дополнительные вызовы метода `load` для сканирования других каталогов на наличие команд Artisan:

```php
/**
 * Register the commands for the application.
 *
 * @return void
 */
protected function commands()
{
    $this->load(__DIR__.'/Commands');
    $this->load(__DIR__.'/MoreCommands');

    // ...
}
```

Вы также можете вручную зарегистрировать команде, добавив имя класса в свойство `$commands` файла `app/Console/Kernel.php`. Когда Artisan загрузится, все команды, перечисленные в этом свойстве, будут разрешены [сервис-контейнером](https://github.com/delphinpro/laravel-ru/tree/5424b57a0aabdeb69b9d791b3c6e8986523e7bec/digging-deeper/.../architecture-concepts/container.md) и зарегистрированы в Artisan:

```php
protected $commands = [
    Commands\SendEmails::class
];
```

## Программное выполнение команд

Иногда вы можете захотеть выполнить Artisan-команду за пределами CLI. Например, вы можете захотеть запустить Artisan-команду из маршрута или контроллера. Для этого можно использовать метод `call` фасада `Artisan`. Метод `call` принимает в качестве первого аргумента либо имя команды, либо класс, а в качестве второго аргумента — массив параметров команды. Возвращается код выхода:

```php
Route::get('/foo', function () {
    $exitCode = Artisan::call('email:send', [
        'user' => 1, '--queue' => 'default'
    ]);

    //
});
```

Или же вы можете передать всю команду Artisan в метод `call` в виде строки:

```php
Artisan::call('email:send 1 --queue=default');
```

Используя метод `queue` фасада `Artisan`, вы можете даже ставить команды Artisan в очередь, чтобы они обрабатывались в фоновом режиме вашими [воркерами очереди](/laravel-ru/digging-deeper/queues.md). Перед использованием этого метода, убедитесь, что Вы настроили свою очередь и запустили слушателя очереди:

```php
Route::get('/foo', function () {
    Artisan::queue('email:send', [
        'user' => 1, '--queue' => 'default'
    ]);

    //
});
```

Вы также можете указать соединение или очередь, в которую должна быть отправлена команда Artisan:

```php
Artisan::queue('email:send', [
    'user' => 1, '--queue' => 'default'
])->onConnection('redis')->onQueue('commands');
```

**Передача массивов**

Если ваша команда определяет опцию, которая принимает массив, вы можете передать массив значений в этот параметр:

```php
Route::get('/foo', function () {
    $exitCode = Artisan::call('email:send', [
        'user' => 1, '--id' => [5, 13]
    ]);
});
```

**Передача булевых значений**

Если вам нужно указать значение опции, которая не принимает строковые значения, например, флаг `--force` в команде `migrate:refresh`, вы должны передать `true` или `false`:

```php
$exitCode = Artisan::call('migrate:refresh', [
    '--force' => true,
]);
```

### Вызов команд из других команд

Иногда вам может понадобиться вызвать другие команды из существующей Artisan-команды. Вы можете сделать это, используя метод `call`. Этот метод `call` принимает имя команды и массив параметров команды:

```php
/**
 * Execute the console command.
 *
 * @return mixed
 */
public function handle()
{
    $this->call('email:send', [
        'user' => 1, '--queue' => 'default'
    ]);

    //
}
```

Если вы хотите вызвать другую консольную команду и подавить весь ее вывод, вы можете использовать метод `callSilent`. Метод `callSilent` имеет такую же сигнатуру, как и метод `call`:

```php
$this->callSilent('email:send', [
    'user' => 1, '--queue' => 'default'
]);
```

## Настройка заготовок

Команды `make` консоли Artisan используются для создания различных классов, таких как контроллеры, задания, миграции и тесты. Эти классы генерируются с помощью "заготовок" файлов, которые заполняются значениями, основанными на вводимых вами данных. Однако, иногда Вы можете захотеть внести небольшие изменения в файлы, сгенерированные Artisan. Для этого вы можете использовать команду `stub:published`, чтобы опубликовать наиболее распространенные заготовки для настройки:

```bash
php artisan stub:publish
```

Опубликованные заготовки будут находиться в каталоге `stubs` в корне Вашего приложения. Любые изменения, которые вы сделаете в этих файлах, будут отражены при генерации соответствующих классов, используя команды Artisan `make`.
