Comandos do console
Aprenda a criar seus próprios comandos de console personalizados.
Criando comandos
Para um comando deve-se definir um callback, que pode ser um closure, callable ou um método de uma classe no namespace Commands com o método:
Console::action(
string $name,
string|callable $callback
): Inphinit\Experimental\Cli\Command
Para testar adicione o código a seguir em system/console.php:
use Inphinit\Experimental\Cli\Command;
$console->action('hello', function (Command $command, array $params, array $residues) {
echo 'Hello world!';
});
Então na pasta root do projeto execute o comando:
./run hello
Em Windows execute:
run hello
Se o PHP estiver disponivel via CLI, também é possivel executar:
php run hello
O callback não precisa retornar um valor, ou pode retornar null, mas é possivel enviar exit status (também chamado de exit code ou exit value) quando o comando terminar, usando int, exemplo:
use Inphinit\Experimental\Cli\Command;
$console->action('hello', function (Command $command, array $options, array $residues) {
if (condition) {
echo 'Success!';
return 0;
}
echo 'Fail!';
return 1;
});
Observe que, se você usar return; ou return null;, o exit status será int(0).
Definindos opções
Um comando pode possuir uma ou mais opções, usando o método:
Command::setOption(
string $long,
string|null $short = null,
int $modes = 0,
string|null $format = null,
string|null $description = null
)
Exemplo de uso:
use Inphinit\Experimental\Cli\Command;
$my_command = $console->action('flower', function (Command $command, array $options, array $residues) {
$name = $options['name'];
$color = $options['color'];
if ($name !== null) echo "Name: {$name}\n";
if ($color !== null) echo "Color: {$color}\n";
});
$my_command->setOption('name');
$my_command->setOption('color');
Executando:
./run flower --name Lily
Obeterá a saída:
Name: Lily
Executando:
./run flower --color red
Obeterá a saída:
Color: red
Executando:
./run flower --name Daisy --color purple
Obeterá a saída:
Name: Daisy
Color: purple
O método setOption() retorna sempre o próprio comando, o que permite simplificar a declaração em alguns casos, como no exemplo:
use Inphinit\Experimental\Cli\Command;
$console->action('flower', function (Command $command, array $options, array $residues) {
// Something
})->setOption('name')->setOption('color');
Definindo opções short
Opções curtas são apelidos que correspondem a opções longas que utilizam um único caractere após o sinal -, elas devem ser definidas no segundo parâmetro de setOption(), por exemplo:
$my_command->setOption('name', 'n');
$my_command->setOption('color', 'c');
Então poderá executar:
./run flower -n Daisy -c purple
Definindo opções obrigatórias
Opções por padrão são opcionais, e quando o comando não recebe o valor, o item no array vindo no segundo parametro do callback (no exemplo $options) irá obter o valor null, mas é possivel tornar a opção obrigatória, passando a flag Command::ARG_REQUIRED:
$my_command->setOption('name', 'n', Command::ARG_REQUIRED); // Required
$my_command->setOption('color', 'c'); // Optional
Ao executar o comando sem o parametro uma exception será lançada, e por convenão no ./run a mensagem da exception será enviada para o STDERR. Exemplo:
./run flower --color red
Saída:
`--name` (or `-n`) is missing
Se precisar definir uma opção como obrigatória sem uma opção short, defina o segundo parametro como null:
$my_command->setOption('name', null, Command::ARG_REQUIRED);
Definindo opções sem valor
Uma opção sem valor deve receber usar a flag Command::ARG_NO_VALUE, exemplo:
use Inphinit\Experimental\Cli\Command;
$my_command = $console->action('hello', function (Command $command, array $options, array $residues) {
var_dump($options['message']);
var_dump($options['update']);
var_dump($options['restart']);
});
// Optional
$my_command->setOption('update', null, Command::ARG_NO_VALUE);
// Required
$my_command->setOption('restart', null, Command::ARG_NO_VALUE|Command::ARG_REQUIRED);
E pode ser executado como:
./run hello --message "Hi!" --update --restart
Ao tentar passar um valor:
./run hello --restart foobar
Obeterá a saída:
`--restart` must not have a value, 'foobar' given
Validando formato dos valores das opções
O quarto parametro de setOption() pode receber uma expressão regular completa, permitindo bastante flexibilidade para validar os valores, exemplo:
use Inphinit\Experimental\Cli\Command;
$my_command = $console->action('hello', function (Command $command, array $options, array $residues) {
var_dump($options['foo'], $options['bar']);
});
// Optional
$my_command->setOption('foo', null, 0, '#^[a-z]+$#');
// Required
$my_command->setOption('bar', null, Command::ARG_REQUIRED, '#^\d+$#');
Tolerando opções residuais
Por padrão comandos que recebem opções não definidas irão fazer o comando falhas. Exemplo:
./run hello --foo test --bar 1 --baz 1 --other -a -b -c
Obeterá a saída:
Unexpected options: baz, other, a, b, c
Mas é possivel ignorar esse erro e continuar o comando usando o método enableResidues(true) no comando:
use Inphinit\Experimental\Cli\Command;
$my_command = $console->action('hello', function (Command $command, array $options, array $residues) {
echo 'foo: ', $options['foo'], "\n";
echo 'bar: ', $options['bar'], "\n";
var_dump($residues);
});
$my_command->setOption('foo', null, 0, '#^[a-z]+$#');
$my_command->setOption('bar', null, Command::ARG_REQUIRED, '#^\d+$#');
$my_command->enableResidues(true);
O comando será executado normalmente e as opções inesperadas serão passadas para o terceiro parametro do callback (no exemplo $residues), obtendo a saída:
foo: test
bar: 1
array(5) {
["baz"]=>
string(1) "1"
["other"]=>
NULL
["a"]=>
NULL
["b"]=>
NULL
["c"]=>
NULL
}
Usando classe para definir um comando
Para definir um ou mais comandos baseados em uma classe, crie um arquivo ./system/Commands/Example.php contendo:
<?php
namespace Commands;
use Inphinit\Experimental\Cli\Command;
class Example
{
/**
* @param \Inphinit\Experimental\Cli\Command $command
* @param array $options
* @param array $residues
*/
public function index(Command $command, array $options, array $residues)
{
echo 'Hello World!';
}
}
E então definir no ./system/console.php:
$console->action('hello', 'Example::index');
Executando comando fora do terminal
É possivel executar o comando via script, sem passar por um terminal. Ao criar um comando em system/console.php, como exemplo:
$console->action('mycommand', function (Command $command, array $params, array $residues) {
echo 'Hello!';
});
Em uma rota no contexto web (no arquivo main.php) é possivel chamar o comando através de:
use Inphinit\Experimental\Cli\Console;
$app->action('GET', '/run', function () {
$output = Console::run('mycommand', [], $status);
echo 'Exit status:', $status;
echo 'Output:', $output;
});
Então ao navegar para um endereço como http://localhost:5000/run, conforme o exemplo, írá ver algo como:
Exit status: 0
Output: Hello!
Se o comando espera opções, use o segundo parametro como uma array associativa, sem usar o -- ou -, para enviar os valores:
$output = Console::run('mycommand', [
'foo' => 'test 1',
'bar' => 'test 2'
], $status);
Será o equivalente:
./run mycommand --foo "teste 1" --bar "teste 2"
Comandos built-in
Todo projeto possui alguns comandos úteis para otimizar ou controlar a aplicação:
| Comando | Descrição |
|---|---|
run app:down |
Ativar o modo de manutenção |
run app:up |
Desativar o modo de manutenção |
run env:boot |
Otimiza as .env variáveis de ambiente do arquivo, adicionando-as ao cache de inicialização |
run env:source |
Desative o cache de variáveis .env, fazendo com que todas as requisições exijam que o aplicativo analise o arquivo |
run pkg:up |
Otimiza o carregamento de pacotes instalados via Composer para utilizar o "inphinit-autoload". Normalmente, não é necessário executar este comando, pois ele é executado automaticamente quando um pacote é instalado ou removido |
run serve |
Inicia um servidor de desenvolvimento |