PHP 5.3 parte IV: Arquivos Phar.

Posted on dezembro 25, 2009. Filed under: PHP |

Arquivos Phar são semelhantes aos arquivos JAR do Java. Recurso incluído na versão 5.3 do php, esta nova funcionalidade permite que você distribua sua aplicação PHP inteira ou uma biblioteca em um único arquivo, chamado de arquivo Phar. Esta funcionalidade tornou-se nativa do php na versão 5.3. Não existe uma ferramenta externa para criar arquivos phar como acontece no java. Toda manipulação, criação e utilização dos arquivos são realizados através de códigos PHP. Pelo fato de ser nativo, praticamente não há perca de desempenho em sua utilização.

Criando arquivos Phar

Para criar arquivos Phar será necessário alterar a diretiva phar.readonly no php.ini para Off. Por padrão, esta diretiva vem habilitada por motivos de segurança. Em servidores de produção, arquivos Phar não precisam ser criados, somente executados, por isso a preocupação com a segurança.

O primeiro passo para criar um arquivo Phar é instanciar a classe Phar:

<?php
$p = new Phar('/project/app.phar', 0, 'app.phar');
$p->startBuffering();

O primeiro parâmetro para o construtor da classe Phar é o caminho no sistema de arquivos onde será criado ou acessado o arquivo Phar.
O segundo parâmetro são flags passadas para a classe pai.
O terceiro parâmetro é um alias que poderá ser utilizado para referenciar o arquivo Phar em chamadas de funções de streams.
O método startBuffering é utilizado com a finalidade de desempenho. Todas mudanças que fizermos no arquivo Phar serão efetivadas somente quando chamarmos a função stopBuffering. Quando não utilizamos startBuffering cada mudança realizada no arquivo Phar será efetivada imediatamente.

Adicionando arquivos

Existem várias maneiras de adicionar arquivos dentro do pacote. Uma delas é utilizando o método “addFile”:
$p->addFile("/project/userBlog.php");
$p->addFile("/project/userCMS.php", "/lib/CMS.php");

Na primeira chamada de método addFile estamos adicionando o arquivo /project/userBlog.php dentro do pacote. O segundo comando é semelhante, porém estamos passando um segundo parâmetro. Através do segundo parâmetro definimos o caminho que o arquivo será armazenado no pacote. Quando precisarmos utilizar esse arquivo no pacote, vamos referênciá-lo através de /lib/CMS.php.

O objeto Phar utiliza ArrayAccess SPL que permite acessar o conteúdo do pacote Phar através de array. É a maneira mais simples de se adicionar arquivos:

<?php
$p['index.php'] = file_get_contents("/project/index.php");
$p['teste.txt'] = "Teste 123 456";

Normalmente quando precisamos adicionar muitos arquivos para dentro do pacote torna-se inviável utilizar as opções anteriores, onde temos que adiocionar um a um. Existem métodos que facilitam essa tarefa, como buildFromDirectory e buildFromIterator.

buildFromDirectory:

$p->buildFromDirectory('/project', '/\.php/');

A função buildFromDirectory adiciona os arquivos de um diretório dentro do pacote Phar. O segundo parâmetro, opcional, é uma expressão regular usada para filtrar os arquivos que serão incluídos. No exemplo anterior estamos incluíndo todos os arquivos com a extensão .php do diretório /project dentro do pacote Phar.

Arquivo Stub

O arquivo Stub é um pedaço de código que será executado quando o arquivo Phar for carregado. Para definir o pedaço de código que será executado ao carregar o arquivo Phar pode-se usar o método setStub que aceita o código em forma de string. Exemplo:

$p->setStub('<?php Phar::mapPhar(); include "phar://app.phar/index.php"; __HALT_COMPILER(); ?>');

O código deve terminar com a função __HALT_COMPILER(). O método statico Phar::mapPhar() lê e inicializa o arquivo Phar a ser executado. O streammer phar:// é usado para referenciar os arquivos que estão dento do pacote Phar. No exemplo anterior ao carregar o arquivo app.phar será executado o arquivo index.php.

Caso não existam nenhum procedimento especial ao carregar o arquivo Phar, onde você deseja simplesmente exeturar um arquivo php diretamente, usá-se o método createDefaultStub. É só passá-lo como parâmetro para o método setStub.

$p->setStub($p->createDefaultStub('index.php'));

Vamos a um exemplo prático onde utilizaremos os conceitos já abordados até aqui. Criar arquivo index.php:
<?php
echo "Olá mundo";

PHP para criar pacote Phar (cria_phar.php):
<?php
$p = new Phar('teste.phar', 0, 'teste.phar');
$p->startBuffering();
$p['index.php'] = file_get_contents("index.php");
// $p->addFile('index.php'); - segunda opção para incluir arquivos.
$p->setStub($p->createDefaultStub('index.php'));
$p->stopBuffering();

Criando o arquivo teste.phar através da linha de comando:

# php cria_phar.php

Após a execução do script acima será criado o arquivoteste.phar.
Executando o pacote phar:

# php teste.phar

A saída da execução do script acima será:

Olá Mundo

Trabalhando com arquivos Phar

Integrar arquivos Phar em sua aplicação é simples e fácil. A maneira mais simples de se usar arquivos de dentro do pacote Phar é incluí-los em sua aplicação da mesma maneira que você inclui outros arquivos usando include.
Parar referênciar algum arquivo dentro do pacote Phar usá-se o streammer phar://. Segue abaixo o exemplo:

<?php
include 'teste.phar';
include 'phar://teste.phar/index.php';

Na primeira linha estamos incluíndo o pacote Phar. Ao rodar essa linha será chamado o código especificado no stub, que no caso é a execução do arquivo index.php. Na segunda linha estamos incluindo diretamente o arquivo index.php. Qualquer uma das duas chamadas são válidas e uma não depende da outra para rodar. Poderíamos ter chamado ou somente a primeira linha ou somente a segunda linha. De acordo com a segunda linha do exemplo podemos observar que é possível incluir qualquer arquivo existente dentro do pacote Phar.

Agora vamos ver um exemplo de como trabalhar com arquivos Phar via web. Para isso vamos utilizar o método statico Phar::webPhar. Ele funciona como um front controller redirecionando as requisições web para os arquivos dentro do pacote Phar. No próximo exemplo vamos criar um novo arquivo Phar para ser utilizado em um ambiente web:

<?php;
// Criando arquivo Phar:
try {
  $phar = new Phar('exemplo.phar');
  $phar['index.php'] = '<?php echo "Hello World Index"; ?>';
  $phar['admin.php'] = '<?php echo "Hello World Admin"; ?>';
  $phar->setStub('<?php Phar::webPhar(); __HALT_COMPILER(); ?>');
} catch (Exception $e) {
// Tratando erro
}
print "Arquivo Phar criado";

O método webPhar() deve estar dentro do código stub e será executado ao chamarmos o pacote exemplo.phar. Após criarmos o arquivo exemplo.phar devemos colocá-lo dentro do diretório raiz do servidor web. Devemos configurar o servidor web para que ele saiba o quê fazer com arquivos de extensão .phar. Segue abaixo a configuração que deve ser realizada no apache:

AddType application/x-httpd-php .php .phar

Apenas adicionamos a extensão .phar ao final da cláusula AddType já existente no httpd.conf.

Agora podemos chamar a aplicação pelo browser:

http://localhost/exemplo.phar
A saída no browser será:
Hello World Index

Para chamar o arquivo admin.php:

http://localhost/exemplo.phar/admin.php
A saída no browser será:
Hello World Admin

Outros formatos

Além do formato padrão, formato Phar, você pode trabalhar com outros formatos. Outros formatos permitidos são ZIP e TAR. Vamos aos exemplos:

Convertendo para ZIP:
$p = $p->convertToExecutable(Phar::ZIP);

Convertendo para TAR/GZ:
$p = $p->convertToExecutable(Phar::TAR, Phar::GZ, '.phar.tgz');

Finalizando

Existem diversas outras maneiras de se trabalhar os arquivos Phar. Neste artigo tentei demonstrar os principais métodos da classe Phar. Para se aprofundar acesse http://www.php.net/phar.

Make a Comment

Deixe uma resposta para Augusto Cancelar resposta

Preencha os seus dados abaixo ou clique em um ícone para log in:

Logotipo do WordPress.com

Você está comentando utilizando sua conta WordPress.com. Sair /  Alterar )

Foto do Google

Você está comentando utilizando sua conta Google. Sair /  Alterar )

Imagem do Twitter

Você está comentando utilizando sua conta Twitter. Sair /  Alterar )

Foto do Facebook

Você está comentando utilizando sua conta Facebook. Sair /  Alterar )

Conectando a %s

9 Respostas to “PHP 5.3 parte IV: Arquivos Phar.”

RSS Feed for Pasqua Tecnologia Comments RSS Feed

Muito legal, só que ao instanciar a classe Phar no meu Wamp ele diz que a classe não foi encontrada. Já adicionei a extensão no php.ini

Marcelo,

A extensão deve ser adicionada no httpd.conf e não no php.ini

Caso ocorra problema, verifique os seguintes passos:

– Wamp deve estar com a versão do PHP no mínimo na 5.3.
– A diretiva phar.readonly deve estar Off no php.ini.
– Criar o arquivo phar setando a função webPhar():


  $phar = new Phar('exemplo.phar');
  $phar['index.php'] = '<?php echo "Hello World Index"; ?>';
  $phar['admin.php'] = '<?php echo "Hello World Admin"; ?>';
  $phar->setStub('<?php Phar::webPhar(); __HALT_COMPILER(); ?>');

– Fazer com que o Apache enxergue a extensão .phar. Adicionando a extensão no httpd.conf e não no php.ini: Procure a seguinte linha já existente no httpd.conf e adicione a extensão .phar

AddType application/x-httpd-php .php .phar

– Copiar o exemplo.phar gerado para dentro do DocumentRoot
– Testar: http://localhost/exemplo.phar

Caso ocorra algum erro, envie a mensagem de erro aqui.

Olá Douglas,

Parabéns pelo ótimo artigo sobre arquivos Phar.

Abraço!

Olá, muito bom este artigo.

Não conhecia, após lêr imediatamente atualizei o ambiente de desenvolvimento para o php 5.3 utilizando o wamp.

Esta tudo ok no PHP.INI, a extenção esta descomentada, porém na pasta ext do php não tem a dll correspondente, que é a php_phar.dll.

Também não sei o que tenho que fazer no httpd.conf.

O erro apresentado é :

Fatal error: Uncaught exception ‘UnexpectedValueException’ with message ‘creating archive “teste.phar” disabled by INI setting’ in D:\Desenvolvimento\www\tableless\pharIni.php:2 Stack trace: #0 D:\Desenvolvimento\www\tableless\pharIni.php(2): Phar->__construct(‘teste.phar’, 0, ‘teste.phar’) #1 {main} thrown in D:\Desenvolvimento\www\tableless\pharIni.php on line 2

Quando verifico a existencia da classe com o php ele diz que a classe existe.

Me ajuda, to loco pra ver isso funcionar.

Valeu

Welinton,

No php.ini, Localize a linha abaixo:

;phar.readonly = On

Altere para:

phar.readonly = Off

No arquivo httpd.conf, localize a linha abaixo:

AddType application/x-httpd-php .php

Altere para:

AddType application/x-httpd-php .php .phar

Reinicie o Apache e teste novamente!

Perfeito, muito bom mesmo, sempre procurei alguma forma decompilar o php e esta forma sem dúvida é a melhor até por ser nativo do php.

Agora me fala uma coisa, não tem como automatizar o processo de addFile?

Welinton,

Normalmente quando precisamos adicionar muitos arquivos para dentro do pacote torna-se inviável utilizar as opções anteriores, onde temos que adiocionar um a um. Existem métodos que facilitam essa tarefa, como buildFromDirectory e buildFromIterator.

buildFromDirectory:

$p->buildFromDirectory(‘/project’, ‘/\.php/’);

A função buildFromDirectory adiciona os arquivos de um diretório dentro do pacote Phar. O segundo parâmetro, opcional, é uma expressão regular usada para filtrar os arquivos que serão incluídos. No exemplo anterior estamos incluíndo todos os arquivos com a extensão .php do diretório /project dentro do pacote Phar.

Olá tudo bem, gostei muito da sua explicação, porem tenho algumas duvidas que se puder me ajudar com elas fico agradecido.

1 – tenho um sistema de ordem de serviços feito em php (meu ganha pão uahau) ele tem seus diretorios imagens classes etc, a pergunta é: posso adicionar toda a pasta do meu sistema e criar um “sis.phar” contendo todo os arquivos imagens, classes etc.

2 – é como um compilador; tipo meu cliente vai poder descompactar o sistema e pegar meus fontes ou não é possivel

3 – se meu sistema tem um modulo de upload, como eu uparia uma imagem para dentro de uma pasta no arquivo phar

Olá Augusto,

Vamos as respostas:

1 – Sim, é possível adicionar todos os arquivos dentro do pacote phar. Isto inclui imagens, css, javascript e php. Sugiro usar os métodos buildFromDirectory ou buildFromIterator. O seguinte exemplo adiciona todos arquivos idenpendente do tipo que ele seja:

$p->buildFromDirectory(‘/project’);

2 – O phar não funciona como compilador, mas como um “compactador”. Portanto, através das próprias funções da extensão phar para php é possível descompactar o pacote.

3 – Você pode manter os arquivos de upload em um diretório separado do pacote. Ou após o upload do arquivo, você pode incluir o arquivo recém enviado no upload no pacote phar utilizando o método “addFile”.

Abraços,
Douglas


Where's The Comment Form?

Liked it here?
Why not try sites on the blogroll...

%d blogueiros gostam disto: