Aplicativos de Console
====================

Aplicativos de console são utilizados para realizar algum trabalho offline necessário
por um aplicativo Web online como, geração de código, compilação do índice de busca,
envio de e-mail, etc. O Yii fornece um framework para escrever aplicativos de console
de uma maneira orientada a objetos. Ele permite que um aplicativo de console acesse os
recursos (por exemplo, conexões a banco de dados) que são utilizados por uma aplicação
Web online.


Visão Geral
--------

O Yii representa cada tarefa de console como um [comando|CConsoleCommand].
Um comando de console é uma classe que estende de [CConsoleCommand].

Quando utilizamos a ferramenta `yiic webapp` para criar o esqueleto inicial de uma
aplicação Yii, podemos encontrar dois arquivos no diretório `protected`:

* `yiic`: este é um script executável utilizado no Linux/Unix;
* `yiic.bat`: este é um arquivo batch executável utilizado no Windows.

Na janela de console, podemos informar os seguintes comandos:

~~~
cd protected
yiic help
~~~

Este comando irá mostrar uma lista dos comandos de console disponíveis. Por padrão,
os comandos de console disponíveis, incluem os fornecedidos pelo Yii Framework
(chamados de **comandos de sistema**) e aqueles desenvolvidos pelos usuários para
aplicações individuais (chamados **comandos de usuário**).

Para descobrir como utilizar um determinado comando, podemos executar:

~~~
yiic help <nome-do-comando>
~~~

E para executar um comando, podemos utilizar o seguinte formato:

~~~
yiic <nome-do-comando> [parâmetros...]
~~~


Criando Comandos
-----------------

Comandos de console são armazenados como arquivos de classe dentro do diretório
especificado em [CConsoleApplication::commandPath]. Por padrão, o diretório
`protected/commands` é utilizado.

Uma classe de comando de console deve estender [CConsoleCommand]. Seu nome
deve ter o formato `XyzCommand`, onde `Xyz` referencia o nome do comando com a primeira letra
em maiúsculo. Para exemplificar, o comando `sitemap` deve usar o nome de classe `SitemapCommand`.
Comandos de console são case-sensitive, ou seja, há diferença entre maiúsculas de minúsculas.

> Tip|Dica: Através da propriedade [CConsoleApplication::commandMap], podemos ter classes de comandos
> com diferentes convenções de nomenclatura e localizadas em diferentes diretórios.

Para criar um comando, precisamos sobrescrever o método [CConsoleCommand::run()]
ou desenvolver uma ou mais ações de comando (isto será explicado na próxima sessão).

Quando executamos um comando de console, o método [CConsoleCommand::run()] será
invocado pela aplicação. Qualquer parâmetro de comando será passado
para o método, de acordo com a assinatura de método a seguir:

~~~
[php]
public function run($args) { ... }
~~~

onde `$args` refere-se aos parâmetros extras informados na linha de comando.

Dentro de um comando de console, utilizamos `Yii::app()` para acessar a instância
da aplicação de console, através da qual podemos acessar recursos, tal como a conexão ao banco de dados
(ex: `Yii::app()->db`). Como é possível perceber, a utilização é similar ao modo como é
feita em aplicações Web.

> Info|Informação: A partir da versão 1.1.1, também podemos criar comandos globais que são
compartilhados para **todas** as aplicações Yii no mesmo computador. Para isso, definimos
uma variável de ambiente com o nome `YII_CONSOLE_COMMANDS` que deverá apontar para um
diretório existente. Dentro deste diretório colocamos os arquivos de classe de comandos.


Ações em Comandos de Console
----------------------

> Note|Nota: Esta funcionalidade está disponível desde a versão 1.1.5.

Um comando de console, muitas vezes precisa lidar com diferentes parâmetros de linha de comando,
alguns necessários, outros opcionais. Um comando de console também pode precisar fornecer vários
sub-comandos para lidar com diferentes sub-tarefas. Estes trabalhos podem ser simplificados
utilizando ações de comando de console.

Uma ação de comando de console é um método da classe de comando de console.
O nome do método deve ter o formato `actionXyz`, onde `Xyz` refere-se ao nome
da ação, com a primeira letra em maicúsculo. Por exemplo, o método `actionIndex`
define uma ação chamada `index`.

Para executar uma ação específica, podemos usar o seguinte formado de comando de console:

~~~
yiic <command-name> <action-name> --option1=value --option2=value2 ...
~~~

Os pares de opção-valor adicionais, serão passados como parâmetros de chamada para o método da ação.
O valor da opção `xyz` será passado como o parâmetro `$xyz` para o método da ação.
Por exemplo, se definir a seguinte classe de comando:

~~~
[php]
class SitemapCommand extends CConsoleCommand
{
    public function actionIndex($type, $limit=5) { ... }
    public function actionInit() { ... }
}
~~~

Então, os seguintes comandos de console irão todos resultar na chamada `actionIndex('News', 5)`:

~~~
yiic sitemap index --type=News --limit=5

// $limit possui valor padrão
yiic sitemap index --type=News

// $limit possui valor padrão
// como 'index' é uma ação padrão, podemos omitir o nome da ação
yiic sitemap --type=News

// a ordem das opções não tem importância
yiic sitemap index --limit=5 --type=News
~~~

Se uma opção é informada sem valor (ex: `--type` ao invés de `--type=News`), o valor do parâmetro
correspondente a ação será assumido como um valor boleano `true`.

> Note|Nota: Não são suportados formatos de opções alternativos como
> `--type News`, `-t News`.

Um parâmetro pode ter um valor em array apenas declarando-o como um tipo sugerido de array:

~~~
[php]
public function actionIndex(array $types) { ... }
~~~

Para fornecer os valores ao array, devemos simplesmente repetir a mesma opção na linha de comando, se necessário:

~~~
yiic sitemap index --types=News --types=Article
~~~

O comando acima irá por fim chamar `actionIndex(array('News', 'Article'))`

A partir da versão 1.1.6, o Yii também suporta o uso de parâmetros de ação anônimos e opções globais.

Parâmetros anônimos referem-se aos parâmetros de linha de comando que não estão no formato de opções.
Por exemplo, no comando `yiic sitemap index --limit=5 News` nós temos um parâmetro anônimo cujo valor
é `News` enquanto o parâmetro nomeado `limit` contém o valor 5.

Para usar parâmetros anônimos, a ação de comando deve ser declarada com um parâmetro nomeado `$args`, Para exemplificar,

~~~
[php]
public function actionIndex($limit=10, $args=array()) {...}
~~~

O array `$args` vai guardar todos os valores dos parâmetros anônimos disponíveis.

Opções globais referem-se às opções de linha de comando que são compartilhadas por todas as ações de um comando.
Por exemplo, em um comando que prevê diversas ações, pode ser que cada ação precisa reconhecer uma
opção nomeada `$verbose`. Enquanto podemos declarar um parâmetro `$verbose` em cada método de ação,
uma forma melhor, é declará-la como uma **variável pública** na classe de comando, que transformará
`$verbose` em uma opção global.

~~~
[php]
class SitemapCommand extends CConsoleCommand
{
	public $verbose=false;
	public function actionIndex($type) {...}
}
~~~

O comando abaixo nos permite executar um comando com a opção `verbose`:

~~~
yiic sitemap index --verbose=1 --type=News
~~~


Customizando a Aplicação de Console
--------------------------------

Por padrão, se uma aplicação é criada utilizando a ferramenta `yiic webapp`, a configuração
para a aplicação de console será criada em `protected/config/console.php`. Como um arquivo de configuração
de uma aplicação Web, este arquivo é um script PHP que retorna um array representando os valores iniciais
das propriedades para uma instância de aplicação de console. Como resultado, qualquer propriedade
pública de [CConsoleApplication], pode ser configurada neste arquivo.

Como os comandos de console geralmente são criados para servir uma aplicação Web,
eles precisam acessar os recursos (como as conexões a banco de dados) que serão utilizado por essa aplicação.
Nós podemos fazê-lo no arquivo de configuração da aplicação de console, como a seguir:

~~~
[php]
return array(
	......
	'components'=>array(
		'db'=>array(
			......
		),
	),
);
~~~

Como podemos ver, o formato da configuração é muito semelhante ao que é utilizado na
configuração de um aplicativo Web. Isto porque [CConsoleApplication] e [CWebApplication]
compartilham a mesma classe base.

<div class="revision">$Id: topics.console.txt 2867 2011-01-15 10:22:03Z haertl.mike $</div>
