Консоль Imhotep

Введение

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

# Список доступных команд:
php imhotep list
./imhotep list

# Получить экран справки, на примере команды migrate:
php imhotep help migrate
php imhotep migrate -h

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

./vendor/bin/docker imhotep list

Создание команды

Для создания новой команды вы можете использовать Imhotep команду make:command:

php imhotep make:command SendEmail

После создания команды скорректируйте параметры $defaultName, $defaultDescription и $signature. Свойство $signature определяет вводимые данные.

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

Пример класса команды:

<?php declare(strict_types=1);

namespace App\Console\Commands;

use Imhotep\Console\Command\Command;

class SendEmailCommand extends Command
{
    /**
     * Название команды.
     *
     * @var string
     */
    public static string $defaultName = 'send:email';

    /**
     * Описание команды.
     *
     * @var string
     */
    public static string $defaultDescription = '';

    /**
     * Сигнатура команды.
     *
     * @var string
     */
    protected string $signature = '';

    /**
     * Обработчик команды.
     *
     * @return int
     */
    public function handle(Mailer $mailer): int
    {
        if ($mailer->send(...)) {
            return Command::SUCCESS; // или return 0;
        }
    
        return Command::FAILURE; // или return 1;
    }
}

Создание анонимной команды

В файле routes/console.php вы можете создать анонимные консольные команды на основе замыканий:

Console::command('mail:send {user}', function (Mailer $mailer, string $user) {
    if ($mailer->send($user)) {
        $this->success('Сообщение отправлено.');
    } else {
        $this->error('Ошибка отправки.');
    }
});

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

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

Чтобы указать аргументы и опции, которые должны быть переданы вашей команде при выполнении, необходимо настроить их в свойстве $signature. Это свойство предоставляет удобный способ задать параметры команды в легко читаемом формате.

Правила для аргументов команды:

// Обязательный аргумент
{user}

// Не обязательный аргумент
{user?}

// Массив аргументов
{user*}

// Необязательный массив аргументов
{user?*}

// Необязательный аргумент со значением по умолчанию
{user?=imhotep}

// Необязательный массив аргументов со значением по умолчанию
{user?*=imhotep}

Правила для опций команды:

// Просто опция без значения
{--format}

// Опция с коротким псевдонимом
{--f|format}

// Опция с обязательным значением
{--format=}

// Опции с необязательным значением
{--format=?}

// Опция поддерживающая массив значений, значения обязательны
{--format=*}

// Опция поддерживающая массив значений, значения не обязательны 
{--format=?*}

// Опции со значением по умолчанию
{--format=?default}

Примеры использования:

$signature = 'list {--format=?txt}';

$signature = 'mail:send {name} {type?=register}';

Ввод / Вывод

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

В процессе выполнения команды вы можете использовать методы arguments, argument, hasArgument, options, option, hasOption. Эти функции позволяют проверить наличие аргументов и опций, а также получить нужные данные.

public function handle(): int
{
    // Получить все аргументы в виде массива
    $arguments = $this->arguments();
    
    // Получить аргумент по имени
    $name = $this->argument('name');
    
    // Проверка наличия аргумента
    if ($this->hasArgument('name')) {
        // ...
    } 
    
    // Получить все опции в виде массива
    $options = $this->options();
    
    // Получить опцию по имени
    $format = $this->option('format');
   
   // Проверка наличия опции
    if ($this->hasOption('format')) {
        // ...
    } 
}

Эти методы также доступны и для анонимных команд:

Console::command('mail:send {user?}', function () {
    $user = $this->hasArgument('user') ? 
                $this->argument('user') : 'default';
    // или
    $user = $this->argument('user', 'default')
});

Вывод данных

Для вывода результата выполнения команды, доступен широкий диапазон вариантов:

public function handle(): int
{
    // Отобразить простой текст
    $this->line('Обычный текст');
    
    // Для добавления пустой строки используйте
    $this->newLine();
    // или метод $this->line() без параметров
    $this->line();
    
    // Отображение синего текста
    $this->info('Некоторая информация');
    // Отображение желтого текста
    $this->warn('Некоторая информация');
    // Отображение красного текста
    $this->error('Некоторая информация');
    // Отображение зеленого текста
    $this->success('Некоторая информация');
    
    // Информационные блоки
    $this->blockInfo('Информационное сообщение.');
    $this->blockWarn('Предупреждающие сообщение.');
    $this->blockError('Сообщение об ошибке.');
    $this->blockSuccess('Сообщение об успехе.');
    
    // Отобразить некое сообщение,
    // вторым аргументом можно передать цвет текста
    $this->alert('Обратите внимание!');
    $this->alert('Обратите внимание!', 'red');
    
    // Отобразить маркированный список,
    // вторым аргументом можно передать стиль маркера
    $this->bulletList(['One','Two','Three']);
    $this->bulletList(['One','Two','Three'], '✶');
    $this->bulletList(['One','Two','Three'], '<fg=red>✶</>');
    
    // Отобразить строку: название.......значение
    $this->twoColumnDetail('Label', 'Value');
    
    // Выполнить функцию и отобразить время выполнения и статус:
    // Например: Обновление данных.......0.0234s DONE
    $this->task('Задача', function () {
        sleep(1);
        
        // Если задача не выполнена, верните false
        return false;
    });
}

Испытайте каждый из предложенных способов на практике. Эти методы также доступны для использования анонимными командами.

Программный запуск команд

В случае необходимости можно запустить команду с помощью метода call фасада Console. В качестве первого аргумента передаётся сигнатура команды или её имя, а вторым аргументом можно указать массив параметров команды. После выполнения команды возвращается код завершения.

use Imhotep\Facades\Console;

Route::get('/version', function () {
    // Первый вариант, команда передана полностью в виде строки
    $exitCode = Console::call('list --format=json');
    // Второй вариант, параметры команды переданы массивом
    $exitCode = Console::call('list', ['--format' => 'json']);
    // Получение результата выполнения консольной команды
    $listJson = Console::output();
});

Чтобы вызвать команду из другой, используйте методы call или callSilent:

public function handle(): int
{
    // Результат выполнения будет выведен на экран
    $this->call('list', ['--format' => 'json']);
    
    // Тихий вызов, результат не будет выведен на экран
    $this->callSilent('mail:send', [
        'user' => 1, '--queue' => 'default'
    ]);
    
    // ...
}

События

  • Событие Imhotep\Console\Events\ConsoleStarting запускается перед запуском консольного приложения.
  • Событие Imhotep\Console\Events\CommandStart запускается перед началом выполнения команды.
  • Событие Imhotep\Console\Events\CommandFinish запускается после выполнения команды.