Extendendo o Zend_Tool
Visão Geral do Zend_Tool
Zend_Tool_Framework é uma framework para expor as funcionalidades
comuns, tais como a criação da estrutura do projeto, geração de código, geração de
índice de pesquisa, e muito mais. Funcionalmente pode ser escrito e exposto por meio de
classes PHP dentro do include_path do PHP,
permitindo uma flexibilidade incrível de implementação. A funcionalidade pode ser consumida
escrevendo implementação e/ou clientes de protocolo-específico -- tais como clientes console,
XML-RPC, SOAP, e muito mais.
Zend_Tool_Project desenvolve e amplia os recursos do
Zend_Tool_Framework ao de gerenciar um "projeto". Em geral,
um "projeto" é um esforço planejado ou uma iniciativa. No mundo da informática, projetos
em geral são uma coleção de recursos. Esses recursos podem ser arquivos, diretórios,
bases de dados, esquemas, imagens, estilos e muito mais.
Extensões do Zend_Tool_Framework
Arquitetura Geral
Zend_Tool_Framework fornece o seguinte:
Interfaces comuns e abstratas que permitem a
desenvolvedores criar funcionalidades e capacidades que são
invocadas por clientes da ferramenta.
Funcionalidade base de clientes e uma implementação
concreta do console que conectam ferramentas externas e interfaces para o
Zend_Tool_Framework. O cliente do console pode ser utilizado em ambientes CLI,
como console unix e o console do Windows.
Interfaces de "Provider" e "Manifest" que
podem ser usadas pela ferramenta do sistema. "Providers" representam o
aspecto functional do framework, e define as ações que os clientes
da ferramenta podem chamar. "Manifests" age como registros de metadados
que proveem contexto adicional para os vários providers definidos.
Um sistema de loading introspectivo que irá
examinar o ambiente a procura de providers e determinar o que é necessário
para chama-los.
Uma conjunto padrão de sistemas de providers que
permite o sistema relatar o que todos os recursos do sistemas são, bem como
fornecer um feedback útil. Ele também inclui um compreessível "Systema de Ajuda".
Definições que você deve estar ciente de através deste manual com relação
ao Zend_Tool_Framework incluem:
Zend_Tool_Framework - O framework que expõe
recursos da ferramenta.
Tooling Client - Uma ferramenta de desenvolvimento que se conecta
ao e consome Zend_Tool_Framework.
Client - O subsistema do
Zend_Tool_Framework que expoe uma interface tal que
tooling clients podem conectar, pesquisar e executar comandos.
Console Client / Command Line Interface /
zf.php - A tooling client para a linha
de comando.
Provider - Um subsistema e uma coleção de funcionalidades
internas que o framework exporta.
Manifest - Um subsistema para definição,
organização, e divulgação de dados exigidos pelo provider.
Zend_Tool_Project Provider - Um conjunto de providers
especificamente para criação e manutenção de projetos baseados no Zend Framework.
Entendendo o Cliente CLI
A CLI, ou ferramenta de linha de comando (internamente
conhecida como ferramenta de console), é atualmente a interface primária para enviar
pedidos ao Zend_Tool requests. Com a ferramenta CLI,
desenvolvedores podem enviar pedidos para a ferramenta dentro da "janela de linha de comando", também
comumente conhecida como janela do "terminal". Este ambiente é predominante em
embientes *unix, mas também tem uma implementação comum no Windows como o
cmd.exe, console2 e também com o projeto Cygwin.
Configuração da ferramenta CLI
Para distribuir pedidos via cliente de linha de comando, primeiro você
precisa configurar o cliente para que seu sistema possa manipular os
comandos "zf". O cliente de linha de comando, para todos as intenções e
propósitos, é o arquivo .sh ou .bat
que é provido com a sua distribuição do Zend Framework. No trunk, ele pode ser
encontrado aqui:
http://framework.zend.com/svn/framework/standard/trunk/bin/.
Como você pode ver, existem 3 arquivos no diretório /bin/:
zf.php, zf.sh, e
zf.bat. O zf.sh e o zf.bat
são os pacotes específicos do sistema operacional: zf.sh para ambientes
*nix, e zf.bat para ambientes Win32. Estes empacotadores clientes são
responsáveis por procurar o php.exe correto, achando o zf.php, e
passando o pedido para o cliente. O zf.php, é responsável por
manipular a identificação do seu ambiente, construindo um include_path adequado, e passar o
que é fornecido na linha de comando para o componente de biblioteca adequado
para a expedição.
Finalmente, você quer garantir duas coisas para fazer tudo funcionar
independentemente do sistema operacional em que você está:
zf.sh/zf.bat acessível a partir do path do sistema.
Esta é a capacidade de chamar zf de qualquer lugar na sua linha de comando,
independentemente de qual é o seu diretório de trabalho atual.
ZendFramework/library estar no seu
include_path.
Nota: enquanto os acima são os requisitos ideais, você pode simplesmente
baixar o Zend Framework e esperar que ele funcione como ./path/to/zf.php
algum comando..
Configurando a ferramenta CLI em Sistemas Unix-like
A configuração mais comum no ambiente *nix, é copiar o zf.sh e
o zf.php no mesmo diretório que o seu binário PHP.
Isto pode geralmente ser achado nos seguintes lugares:
Para achar a localização do seu binário PHP, você pode executar
'which php' na linha de comando. Isto retornará a localização do binário do PHP
que você está usando para rodar scripts PHP no seu ambiente.
O próximo passo é certificar que a biblioteca Zend Framework está configurada
corretamente dentro do sistema de include_path do
PHP. Para achar onde seu include_path
está localizado, você pode executar php -i e olhar para
a variável include_path, o mais sucintamente, executar
php -i | grep include_path. Uma vez que você tenha achado
onde seu include_path está localizado (isto irá geralmente
estar em algum lugar como /usr/lib/php,
/usr/share/php, /usr/local/lib/php, ou
similar), certifique que o conteúdos do diretório /library/
estão colocados dentro do seu diretório include_path
especificado.
Uma vez que você tenha terminado estas duas coisas, você deve ser capaz de digitar
um comando e obter devolta a resposta adequada como:
Se vocÊ não ver isto digitado na saída, volte e verifique sua configuração
para ter certeza que tem todas as partes necessárias in devido lugar.
Existem uma combinação de configurações alternativas que você pode querer empregar
dependendo das configurações dos servidores, seu nível de acesso, ou
por outras razões.
Configuração Alternativa envolve guardar o download do
Zend Framework junto como está, e criar um link de um local PATH
para o zf.sh. O que isto significa é que você coloca o conteúdo
do download do Zend Framework em uma localização tal como /usr/local/share/ZendFramework,
ou mais localmente como /home/username/lib/ZendFramework, e cria
um link simbólico para o zf.sh.
Assumindo que você quer colocar o link dentro de /usr/local/bin
(isto pode também funcionar colocando o link dentro de /home/username/bin/
por exemplo) você poderia dgitar um comando similar a este:
Isto irá criar um link que você poderá ser capaz de acessar globalmente
na linha de comando.
Configurando a ferramenta CLI no Windows
A confuguração mais comum no ambiente Win32, é copiar o
zf.bat e o zf.php para dentr do mesmo
diretório do seu binário PHP. Este pode geralmente ser achado
nos seguintes lugares:
Você deve ser capaz de rodar php.exe na linha de comando.
Se você não for capaz, primeiro verifique a documentação que veio com sua
distribuição PHP, ou tenha certeza que o caminho para o
php.exe está na sua variável de ambiente
PATH do Windows.
O próximo passo é ter certeza que a biblioteca do Zend Framework
está configurada corretamente dentro do sistema de include_path
do PHP. Para achar onde seu include_path
está localizado, você pode digitar php -i e olhar para a
variável include_path, ou mais sucintamente executar
php -i | grep include_path se você tem um Cygwin configurado
com grep disponível. Uma vez você tenha achado onde seu include_path
está localizado(isto irá geralmente ser algo como C:\PHP\pear,
C:\PHP\share,C:\Program%20Files\ZendServer\share
ou similar), verifique que os conteúdos do diretório library/ estão postos dentro
do seu diretório include_pathespecificado.
Uma vez tenha terminado aquilas duas coisas, você deve ser capaz de enviar um
comando e receber o devida resposta como:
Se você não ver isto digitado na saída, volte e verifique sua configuração
para ter certeza que você tem todas as partes necessárias no lugar correto.
Existe uma combinação de configurações alternativas que você pode querer empregar
dependendo das configurações do seu servidor, do seu nível de acesso, ou de
outras razões.
Configuração Alternativa envolve guardar o download do
Zend Framework junto como está, e alterar ambos seu sistema de PATH
bem como o arquivo php.ini. No seu ambiente de usuário,
tenha certeza de adcionar C:\Path\To\ZendFramework\bin,
então seu arquivo zf.bat será executável. Também, altere
o arquivo php.ini certificando que
C:\Path\To\ZendFramework\library está no seu
include_path.
Outras Considerações de Configuração
Se por alguma razão você não quiser a biblioteca do Zend Framework dentro
do seu include_path, existe uma outra opção. Existem
duas variáveis de ambiente especiais que o zf.php irá
utilizar para determinar a localização da sua instalação do Zend Framework.
A primeira é ZEND_TOOL_INCLUDE_PATH_PREPEND, que irá
preceder o valor da variável de ambiente para o sistema de (php.ini)
include_path include_path antes
da carga do cliente.
Alternativamente, você pode querer usar ZEND_TOOL_INCLUDE_PATH
para substituir completamente o sistema de
include_path para um que faça sentido especialmente para
a ferramente de linha de comando zf.
Criando Providers
Em geral, um provider, por si só, é nada mais que o a casca para um
desenvolvedor para agrupar-se algumas das capacidades que eles desejam
enviar com um o cliente de linha de comando (ou outro). Ele é um análogo
para o que um "controller" é dentro da sua aplicação MVC.
Como o Zend_Tool encontra seus Providers
Por padrão Zend_Tool usa o BasicLoader para encontrar
todos os providers que você pode rodar. Ele itera recursivamente todos
os diretórios do include path e abre todos os arquivos que terminam
com "Manifest.php" ou "Provider.php". Todas as classes naqueles arquivos
são inspecionadas se implementam ou Zend_Tool_Framework_Provider_Interface
ou Zend_Tool_Framework_Manifest_ProviderManifestable.
Instancias da interface do provider implementam a real funcionalidade e
todos os métodos públicos estão acessíveis como actions do provider.
A interface ProviderManifestable de qualquer forma requer a implementação de um
metodo getProviders() que reforna um array de
instâncias da interface provider.
As seguintes regras de nomeação aplicaveis em como você pode acessar os providers
que foram encontrados pelo IncludePathLoader:
A última parte da sua divisão do classname por underscore é usado
para o nome do provedor, por exemplo, "My_Provider_Hello" permite ao seu
provider a ser acessível pelo nome de "hello".
Se o seu provider tem um método getName()
ele irá ser usado ao invés da maneira anterior para determinar
o nome.
Se o seu provider tem um prefixo "Provider", por exemplo ele é chamado
de My_HelloProvider, isto será retirado
do nome, assim o provider será chamado "hello".
O IncludePathLoader não permite links simbólicos, que significa
que você não pode linkar funcionalmente o provider no seus inclide paths,
eles tem que estar fisicamente presentes nos inclide paths.
Expondo Seus Providers com um Manifest
Você pode expor seus providers para Zend_Tool
oferecendo um manifest com a nome de arquivo especial terminando com
"Manifest.php". Um Provider Manifest é uma implementação do
Zend_Tool_Framework_Manifest_ProviderManifestable
e requer o método getProviders() para retornar
uma array providers instânciados. Em antecipação do seu primeiro próprio
provider My_Component_HelloProvider nós iremos
criar o seguinte manifest:
Instruções Básicas para Criação de Providers
Como um exemplo, se um desenvolvedor quer adicionar a capacidade de apresentar
a versão de um arquivos de dados que seu componente de terceiros está usando,
exite apenas uma classe que o desenvolvedor precisaria implementar.
Asumindo que o componente é chamado My_Component,
Ele poderia criar uma classe chamada My_Component_HelloProvider
em um arquivo nomeado de HelloProvider.php em algum lugar no
include_path. Esta classe implementaria Zend_Tool_Framework_Provider_Interface,
e o corpo deste arquivo apenas teria que parecer com o seguinte:
Dado o códifo acima, e assumindo que o desenvolvedor deseja acessar
esta funcionalidade através do cliente de console, a chamada se pareceria
com isto:
O objeto response
Como assumido na arquitetura da sessão Zend_Tool permite
unir diferentes cliente para usar o seus providers Zend_Tool.
Para manter a conformidade com diferentes clientes você deve usar o objeto de resposta
para retornar mensagens de seus providers em vez de usar echo()
ou um mecanismo de saída semelhante. Reescrevendo nosso provider hello com este conhecimento
isto vai se parecer com:
_registry
->getResponse()
->appendContent("Hello from my provider!");
}
}
]]>
Como você pode ser ele extende o
Zend_Tool_Framework_Provider_Abstract para ter acesso
ao Registry que guarda a instância do Zend_Tool_Framework_Client_Response.
Informações sobre Desenvolvimento Avançado
Passando variáveis para o Provider
O exemplo "Hello World" acima é ótimo para comandos simples, mas
o que dizer sobre algo mais avançado? Como seu script e ferramentas
necessidades crescem, você pode achar que você precisa da capacidade de aceitar
variáveis. Bem como assinaturas de função têm parâmetros, a sua
chamada para a ferramenta também podem aceitar parâmetros.
Just as each tooling request can be isolated to a method within a
class, the parameters of a tooling request can also be isolated in a
very well known place. Parameters of the action methods of a
provider can include the same parameters you want your client to
utilize when calling that provider and action combination. For
example, if you wanted to accept a name in the above example, you
would probably do this in OO code:
The above example can then be called via the command line
zf say hello Joe. "Joe" will be supplied to the provider
as a parameter of the method call. Also note, as you see that the
parameter is optional, that means it is also optional on the command
line, so that zf say hello will still work, and default
to the name "Ralph".
Prompt the User for Input
There are cases when the workflow of your provider requires
to prompt the user for input. This can be done by requesting
the client to ask for more the required input by calling:
_registry
->getClient()
->promptInteractiveInput("Whats your name?");
$name = $nameResponse->getContent();
echo 'Hello' . $name . ', from my provider!';
}
}
]]>
This command throws an exception if the current client is not
able to handle interactive requests. In case of the default Console Client
however you will be asked to enter the name.
Pretending to execute a Provider Action
Another interesting feature you might wish to implement is
pretendability. Pretendabilty is the ability
for your provider to "pretend" as if it is doing the requested
action and provider combination and give the user as much
information about what it would do without
actually doing it. This might be an important notion when doing
heavy database or filesystem modifications that the user might not
otherwise want to do.
Pretendability is easy to implement. There are two parts to this
feature: 1) marking the provider as having the ability to "pretend",
and 2) checking the request to ensure the current request was indeed
asked to be "pretended". This feature is demonstrated in the code
sample below.
_registry->getRequest()->isPretend()) {
echo 'I would say hello to ' . $name . '.';
} else {
echo 'Hello' . $name . ', from my provider!';
}
}
}
]]>
To run the provider in pretend mode just call:
Verbose and Debug modes
You can also run your provider actions in "verbose" or "debug" modes.
The semantics in regard to this actions have to be implemented by you
in the context of your provider. You can access debug or verbose modes
with:
_registry->getRequest()->isVerbose()) {
echo "Hello::say has been called\n";
}
if($this->_registry->getRequest()->isDebug()) {
syslog(LOG_INFO, "Hello::say has been called\n");
}
}
}
]]>
Accessing User Config and Storage
Using the Enviroment variable ZF_CONFIG_FILE or the
.zf.ini in your home directory you can inject configuration parameters into
any Zend_Tool provider. Access to this configuration
is available via the registry that is passed to your provider if you extend
Zend_Tool_Framework_Provider_Abstract.
_registry->getConfig()->username;
if(!empty($username)) {
echo "Hello $username!";
} else {
echo "Hello!";
}
}
}
]]>
The returned configuration is of the type
Zend_Tool_Framework_Client_Config but internally the
__get() and __set() magic
methods proxy to a Zend_Config of the given
configuration type.
The storage allows to save arbitrary data for later reference. This can be
useful for batch processing tasks or for re-runs of your tasks. You can
access the storage in a similar way like the configuration:
_registry->getStorage()->get("myUsername");
echo "Hello $aValue!";
}
}
]]>
The API of the storage is very simple:
When designing your providers that are config or storage aware remember
to check if the required user-config or storage keys really exist for a
user. You won't run into fatal errors when none of these are provided
though, since empty ones are created upon request.
Zend_Tool_Project Extensions
Zend_Tool_Project exposes a rich set of functionality and
capabilities that make the task of creating new providers, specficially those targetting
project easier and more manageable.
Overall Architecture
This same concept applies to Zend Framework projects. In Zend Framework projects,
you have controllers, actions, views, models, databases and so on and so forth. In
terms of Zend_Tool, we need a way to track these types of
resources - thus Zend_Tool_Project.
Zend_Tool_Project is capable of tracking project resources
throughout the development of a project. So, for example, if in one command you
created a controller, and in the next command you wish to create an action within
that controller, Zend_Tool_Project is gonna have to
know about the controller file you created so that you can (in
the next action), be able to append that action to it. This is what keeps our
projects up to date and stateful.
Another important point to understand about projects is that typically, resources
are organized in a hierarchical fashion. With that in mind,
Zend_Tool_Project is capable of serializing the current
project into a internal representation that allows it to keep track of not only
what resources are part of a project at any given time, but
also where they are in relation to one another.
Creating Providers
Project specific providers are created in the same fashion as plain framework
providers, with one exception: project providers must extend the
Zend_Tool_Project_Provider_Abstract. This class comes with
some significant functionality that helps developers load existing project, obtian
the profile object, and be able to search the profile, then later store any changes
to the current project profile.
_loadExistingProfile();
/* ... do project stuff here */
$this->_storeProfile();
}
}
]]>