Distribuição de projetos

Para facilitar a distribuição de sistemas, arquivos e o deploy de aplicações, as linguagens de programação costumam implementar uma forma de “compactação” de arquivos.

Os casos mais conhecidos são os jar’s e war’s do java para, no caso do jar, executar aplicações e distribuir bibliotecas e o war para facilitar o deploy no servidor web.

Também podemos citar os gems do ruby que é uma forma de distribuir bibliotecas e aplicações.

O PHP não é diferente. Na versão 5.3 foi implementado nativamente o suporte aos arquivos phar (coincidência?), antes disso uma extensão da pecl era utilizada para criar os arquivos.

Com os arquivos phar, podemos criar bibliotecas, compactá-las e aproveitar as mesmas em nossos projetos de uma maneira mais clara e inteligente, afinal, em um projeto não precisamos saber onde as classes de terceiros (ou não) estão, apenas precisamos saber que estão lá e como chamá-las para atender nossas necessidades.

Diferente do java em que a IDE, ao fazer o build, automaticamente gera um jar com os fontes e as bibliotecas necessárias (graças ao ant). No PHP temos que criar nosso próprio script para que o phar seja gerado. Em outras palavras, o phar será gerado manualmente. Estes passos podem ser automatizados, claro.

Neste exemplo usarei uma classe simples para gerar o phar, trata-se de uma classe que armazena uma string para encriptação. O código da classe é esse:

<?php
namespace com\pedrojannotti\model;

/**
 * Description of MD5
 *
 * @access public
 * @package model
 * @subpackage security
 * @version 1.0
 *
 * @author Pedro Jannotti <http://pedrojannotti.com>
 * @see http://pedrojannotti.com
 * @since 13/02/2010
 */
class MD5 {
    private $encriptedString;
    public function __construct($string) {
        $this->setEncriptedString(md5($string));
    }

    public function getEncriptedString() {
        return $this->encriptedString;
    }

    private function setEncriptedString($encriptedString) {
        $this->encriptedString = $encriptedString;
    }
}

Bom, com a classe base para o nosso phar pronta, vamos criar agora o script que permite que o arquivo phar seja gerado.

Criarei um arquivo chamado create.php que poderá ser acessado tanto via apache como por linha de comando.

$phar = new Phar('aplicacao.phar');
$phar->startBuffering();
$phar->buildFromDirectory('/var/www/phar1');
$phar->stopBuffering();

O script acima cria um objeto do tipo Phar que recebe em seu construtor o nome do arquivo phar a ser gerado.  A extensão .phar deve ser informada, pois esta compactação também pode gerar arquivos de outros formatos.

A segunda linha do script inicia a gravação iniciando o buffer.

Na terceira linha é onde definimos quais arquivos deveremos incluir no phar. No meu caso, para facilitar, estou criando o meu arquivo phar baseado em um diretório. Utilizando o método buildFromDirectory o objeto busca os outros arquivos de forma recursiva.

A criação do phar pode utilizar vários outros métodos, como addFile, addEmptyDir. Para conhecer todos basta acessar a documentação do phar em http://php.net/manual/en/book.phar.php.

Após a execução do script o arquivo será gerado. Para incluir o arquivo phar em sua aplicação, basta usar o comando require da seguinte forma:

require_once 'phar://aplicacao.phar/';

Se você executar este arquivo em um browser ou em linha de comando você deverá ver a mensagem “hello world” impressa na tela. Isto acontece pois quando estávamos criando o phar não informamos qual seria o arquivo de inicialização do phar, ou seja, qual arquivo deverá ser chamado ao importar o phar no projeto (bootstrap).

Para fazer isso, nosso script de geração do phar mudará um pouco:

$phar = new Phar('aplicacao.phar');
$phar->startBuffering();
$phar->buildFromDirectory('/var/www/phar1');
$phar->setDefaultStub('src/main/php/com/pedrojannotti/model/MD5.php');
$phar->stopBuffering();

O stub do phar é o arquivo de boot ao importar o phar, é ele que será chamado ao importar o phar em seu projeto.

Gere novamente o arquivo e tente requerer novamente o arquivo. Você verá que nenhuma mensagem será exibida em tela.

Para usar a classe agora basta instanciá-la:

<?php
require_once 'phar://aplicacao.phar/';

$md5 = new \com\pedrojannotti\model\MD5("teste");
echo $md5->getEncriptedString();