fev 11
21
Para quem não conhece phar, ou ainda não sabe utilizar, visite um dos seguintes links:
http://www.phpes.org/2011/02/utilizando-arquivos-phar/
http://klaussantana.com/2011/02/utilizando-arquivos-phar/
Para criar ou alterar arquivos phar, você precisa de configurar seu “php.ini” e habilitar a escrita em arquivos phar. Basta mudar a diretiva “phar.readonly” para “1″. Também é necessário que o diretório destino do seu pacote phar tenha permissão de escrita, geralmente um chmod(0777).
A criação de um pacote phar é até um tanto simples:
$package = new Phar("path/myPackage.phar");
Então você já tem um pacote phar para trabalhar. Agora é só começar a adicionar o conteúdo no seu pacote:
$package->addFile("path/to/myFile.php", "new/path/file.php");
Lembrando que o segundo parâmetro deste método é opcional e indica o novo caminho/nome do arquivo dentro do seu pacote phar.
Também existem outros métodos de adicionar arquivos ou conteúdo. Seguem:
$package = new Phar("MyPackage.phar");
$package["/path/to/file.php"] = "";
$package->addFile("path/to/my/outside/file.php");
$package->buildFromDirectory("my/package/dir", '/\.php$/');
Você pode adicionar arquivos acessando o objeto $package como se fosse uma matriz (array), como pode adicionar o arquivo pelo método addFile() ou então construir seu pacote Phar diretamente de um diretório. Também é possível criar seu pacote por meio de um objeto Iterator. No caso de criar um pacote pelo método buildFromDirectory(), caso não seja interesse adicionar todos os arquivos, você pode especificar uma expressão regular como segundo parâmetro para verificação nos nomes dos arquivos.
Um exemplo de como criar um pacote através de um iterator:
$phar = new Phar("myProject.phar");
$phar->buildFromIterator(
new RecursiveIteratorIterator(
new RecursiveDirectoryIterator('/path/to/project')
),
'new/path/to/project');
Mesmo você adicionando os arquivos em um pacote phar, o que acontece quando você inclui diretamente o pacote phar?
include "MyPackage.phar";
Neste caso, não acontece nada. Para que um pacote phar execute alguma instrução é necessário você indicar um arquivo de bootsrap (stub) ou indicar uma string contendo os comandos a serem executados.
/* (...) */
$package->setStub('');
// Ou você pode usar:
$package->setStub($package->createDefaultStub("cli-bootstrap.php", "web-bootstrap.php"));
Quando você configura um Stub no seu pacote, ele será executado sempre que você incluir diretamente o pacote phar ou executá-lo através da api cli, na linha de comando. O segundo método de criar um stub utiliza o método createDefaultStub, que pode conter dois parâmetros. O primeiro parâmetro indica qual arquivo será executado por padrão, e caso o segundo parâmtro tenha sido especificado, então o primeiro será para quando o pacote for executado através do cli e o segundo será executado quando o pacote for chamado através do browser.
Lembre-se que todos os stubs é necessário chamar a função __HALT_COMPILER() do php para que não ocorra um loop infinito ou um erro inexperado. Ainda não foi documentado o motivo de um stub requerer esta função.
Para um pacote phar funcionar como um diretório do servidor, você pode utilizar da seguinte forma:
$package = new Phar("myApplication.phar");
$package->buildFromDirectory("./myApplication/");
$package->setStub('');
Isso vai fazer com que seu pacote, ao ser incluido diretamente ou executado através da linha de comando, responda como um servidor, procurando pelo arquivo index.php no diretório que for especificado. Exemplo:
include "myApplication.phar";
include "phar://myApplication.phar/index.php"; /* equivalente a linha anterior */
// ou //
include "phar://myApplication.phar/app";
include "phar://myApplication.phar/app/index.php"; /* equivalente a linha anterior */
Existem várias outras maneiras de manipular um arquivo phar, mas o necessário para você começar a criar ótimas aplicações encapsuladas já foi explicado. Agora é com você e sua criatividade.
Você pode ler mais sobre como utilizar o phar através da documentação do php.
E uma observação importante:
O phar possúi capacidade de compactar o pacote com zip, bzip e tar.gz, mas não é possível trabalhar com stubs em pacotes compactados. Por este motivo, pacotes compactados são somente úteis para armazenar recursos para sua aplicação, ou aplicações em que seus arquivos devem ser chamadas manualmente, exemplo:
include "phar://myApp.phar/calculator.php";
include "phar://myApp.phar/sql.php";
Para criar pacotes compactados, basta usar da seguinte forma:
$package = new Phar("myApp.phar");
$package->buildFromDirectory("./dir/to/myApp/");
$package->compress(Phar::GZ /* ou Phar::BZ2 */);
/* não é possível utilizar stubs em pacotes compactados */
Mais detalhes em http://www.php.net/manual/en/phar.compress.php.
fev 11
21
Para quem nunca ouviu falar de PHAR, que significa PHP ARchive, se trata de uma extensão do PHP que torna possível encapsular/compactar/agrupar vários arquivos em um único pacote “.phar”, assim como o JAR, do Java. Essa extensão proporciona a capacidade de agrupar uma aplicação inteira em um único arquivo para ser disponibilizado ou apenas utilizado na internet.
Os pacotes phar não são apenas como pacotes RPM do linux, onde a aplicação vem compactada e então é descompactada no sistema de arquivos do computador e compilada de acordo com as configurações do sistema operacional para utilização. Os pacotes PHAR podem ser utilizados imediatamente, sem necessidade de descompactar ou compilar.
Nas versões do PHP posteriores à 5.2 e anteriores à 5.3 é necessário instalar a extensão PECL do phar, que pode ser localizada aqui. A partir da versão 5.3 essa funcionalidade foi adicionada ao código fonte do PHP, não dependendo de instalações ou configurações adicionais.
Mais informações sobre o phar podem ser adquiridas diretamente no manual do php. Infelizmente a documentação sobre o PHAR ainda não foi traduzida por completo para português do brasil.
Para utilizar o phar, é simples, basta incluir o arquivo phar da mesma maneira que se inclui um arquivo php ou html em seu código:
Podia ser mais fácil? Acho que não. Mas apesar de ser tão simples, o que essa linha de comando faz? Nada! Apenas inclui o arquivo myApplication.phar à sua aplicação, e como se trata de um pacote compactado com vários arquivos, o que o PHP deve fazer a partir da inclusão do arquivo?
Na criação de um pacote PHAR, deve ser especificado um Stub que será interpretado pelo PHP como uma fração de código que deve ser executada no momento em que o arquivo for incluido. Geralmente o Stub é um código simples, com duas instruções: um include do arquivo principal da aplicação e um __HALT_COMPILER(). Obs.: a função __HALT_COMPILER() deve sempre estar contida no stub e também deve ser a ultima instrução. O motivo da obrigatoriedade disso ainda não foi documentado.
A inclusão do Stub é sempre feita na criação do pacote, e não cabe mais detalhes sobre isso agora, pois abordarei em outro post sobre criação de pacotes phar.
Quando você tem uma aplicação que funciona bastando sua inclusão simples, basta utilizar um include(“myApplication.phar”). Caso o arquivo não tenha um Stub ou você simplesmente está utilizando um pacote com mero objetivo de agrupar/encapsular arquivos, você sempre pode incluir os arquivos internos do phar pela stream “phar://”.
Obs.: os pacotes PHAR não necessariamente suportam apenas inclusão de arquivos de código. Eles podem conter qualquer tipo de arquivo, inclusive arquivos de imagens, vídeos, músicas, etc.
Para você utilizar os arquivos de imagens dentro de um pacote PHAR diretamente através do navegador é um pouco mais complicado, mas não impossível. Na realidade, eu mentí. É extremamente simples. Basta alterar uma única linha de configuração do seu servidor web. No caso de utilizar o apache, basta adicionar um .phar ao final da linha AddType que configura o php para funcionar no servidor.
AddType application/x-httpd-php .php .phar
A partir daí você pode utilizar algo como isso:
<img src="myTheme.phar/images/mini_banner.png" />
Com a configuração adicional no seu servidor, você também pode utilizar sua aplicação diretamente através da barra de endereço do navegador:
http://meudominio.com/myApplication.phar/blog.php
Se a aplicação for bem encapsulada em um pacote PHAR, você pode acessar sua aplicação apenas referenciando diretamente o pacote, com um stub:
http://meudominio.com/myApplication.phar
Existe a possibilidade de incluir um stub para que o pacote funcione como qualquer diretório no seu servidor, retornando códigos de erro 404 e tudo mais, e a extensão do phar já tem isso pronto pra você. Não vou entrar em detalhes de como incluir um stub desses agora, apesar de ser extremamente simples, vou manter o foco em como utilizar, e esses detalhes coloco em outro post sobre o assunto de Como criar seu pacote PHAR.
“http://meudominio.com/myApplication.phar” seria o equivalente a chamar “http://meudominio.com/myApplication.phar/index.php”, e “http://meudominio.com/myApplication.phar/blog” seria o mesmo que “http://meudominio.com/myApplication.phar/blog/index.php”.
Phar, simples assim.
fev 11
13
“Singleton, é um padrão de projeto de software (do inglês Design Pattern). Este padrão garante a existência de apenas uma instância de uma classe, mantendo um ponto global de acesso ao seu objeto.”
fonte: Wikipédia
Agora que já sabemos do que se trata Singleton, vou ensinar uma forma prática de fazer em php.
class minhaSingleton
{
static protected $Singleton;
public $teste = 'teste'; // para efeito de testes/exemplos
/* previne instanciar deliberadamente */
protected function __construct() { /* seu construtor */ }
/* previne clonar o objeto gerando novas instâncias */
public function __clone()
{
throw new Exception("Não é possível clonar o objeto.");
return null;
}
/* adquire a instância caso exista ou a cria */
static public function &Instance()
{
if ( ! self::$Singleton instanceof self )
{
self::$Singleton = new self;
}
return self::$Singleton;
}
}
/* exemplos... */
$Instancia1 = minhaSingleton::Instance();
$Instancia2 = minhaSingleton::Instance();
$Instancia1->teste = 'variavel';
echo $Instancia2->teste; // imprime: variavel
$Instancia3 = new minhaSingleton(); // erro fatal!
/* NOTA: $Instancia1 ===$Instancia2 é verdadeiro */
Acontece que quando declaro $Instanca1 e $Instancia2 elas recebem uma referência a minhaSingleton::$Singleton, que por sua vez não pode ser acessada de fora do escopo da classe. Caso $Singleton não seja um objeto instanciado da própria classe ele instancia e retorna a referência.
Quando atribuo “variavel” para $Instancia1->teste, na realidade, foi atribuido para minhaSingleton::$Singleton->teste, e quando mando imprimir $Instancia2->teste ele busca em minhaSingleton::$Singleton->teste, o que dá o retorno esperado.
Quanto tento instanciar $Instancia3 pelos métodos convencionais eu recebo um erro fatal, pois como o construtor (__construct()) é protegido, o mesmo não pode ser acessado de fora do escopo da classe.
Basicamente é isso. O link da wikipédia tem alguns outros detalhes para melhor entendimento do que se trata o singleton.
Namespace é um conceito trazido na versão 5.3.0 do PHP. Sua funcionalidade é a de proporcionar um contexto para definições de constantes, funções e classes, não suportando variáveis, chamadas de funções ou qualquer outro tipo de código. Ao migrar para o PHP 5.3 você não será forçado a utilizar os namespaces, tampouco adaptar um código que você pretente reutilizar. Nestes casos, você estará sempre trabalhando num contexto/escopo global. Um breve exemplo:
/* Arquivo Namespace.php */
namespace MeuProjeto;
const version = '1.0';
public function MinhaFuncao() { /* ... seu código aqui ... */ }
E você utilizará da seguinte forma na prática:
/* Arquivo teste.php */
require 'Namespace.php';
echo "Isso é um teste: " .version;
echo "Isso é outro teste: " .MeuProjeto\version;
$Variavel = \MeuProjeto\version;
Ao executar o arquivo teste.php você notará que para o echo da linha 3 será impresso “Isso é um teste: version” ao passo que o echo da linha 4 imprimirá “Isso é outro teste: 1.0″. Também será lançado um E_NOTICE devido ao fato da constante version não existir no contexto em que foi invocada. A linha 4 corrige este problema, invocando a variável version do seu contexto próprio.
A princípio não parece grande coisa, mas traz a possibilidade de um código mais organizado, dentre diversas outras possibilidades, incluindo sobrecarregar funções da linguagem.
Exemplo de como sobrecarregar uma função do sistema:
/* Arquivo namespace.php */
namespace \MeuProjeto;
function &fopen()
{
/* aqui vai código personalizado... */
$args = func_get_args();
$args[0] = realpath($args[0]) .DIRECTORY_SEPARATOR .basename($args[0]);
if ( is_file( $args[0] ) && is_readable( $args[0] ) )
{
$Resource = call_user_func_array('\\fopen', $args);
} else {
$Resource = false;
}
return $Resource;
}
Em outro arquivo, você pode utilizar a função sobrecarregada da seguinte forma:
/* Arquivo teste.php */
@ include 'namespace.php';
use \MeuProjeto;
$fp1 = fopen('meu_log.xml', 'a+');
$fp2 = \fopen('meu_log.xml', 'a+');
Claro que se o arquivo namespace.php não existir o interpretador irá chamar a função fopen da linguagem. Neste exemplo, se o arquivo ‘meu_log.xml’ não existir, $fp1 receberá false porque mesmo explicitando ao fopen que ele deve criar um arquivo caso ele não exista (+), a função que defini retorna false caso não exista um arquivo no caminho indicado. Já $fp2 receberá um resource apontando para o arquivo “meu_log.xml” que foi criado devido a especificação no segundo argumento dado ao \fopen(). A variável $fp2 funciona corretamente porque chama a função built-in do php no escopo global e não utilizará a função personalizada definida no escopo \MeuProjeto.
Hoje eu termino sobre Namespaces por aqui, se aparecer alguma novidade sobre o assunto eu faço um novo post. Se alguém tiver uma correção pra fazer, deixe um comentário.
Mais sobre Namespaces:
http://www.php.net/manual/pt_BR/language.namespaces.php
fev 11
11
Sou bancário e eternamente um estudante de programação e boas práticas. Auto-de-data e muito curioso. Sempre aceito desafios.
Criei este blog para divulgar minhas idéias e compartilhar conhecimentos interessantes que venho adquirindo no dia-a-dia a respeito de vérios assuntos, mas o objetivo principal aqui é o universo da tecnologia, e vou abordar bastante assuntos relacionados a informática e programação voltada para internet, desde assuntos como servidores, banco de dados, padrões na internet, boas práticas, padrões de design de softwares (design patterns) e especificidades da linguagem php, que é minha linguagem principal em termos de desenvolvimento. Eventualmente posso abrodar assuntos relacionados a outras linguagens, como Ruby, Java, ASP, Javascript e outras.
Fiquem ligados, hora ou outra sai novo conteúdo aqui.