Como usar metaprogramação em PHP?
Com PHP, você consegue criar um código que gera outro código, afinal, um script PHP é um arquivo texto.
Mas a linguagem também permite que um script consiga alterar seu próprio comportamento em tempo de execução. Isso pode ser útil para otimizar trechos de código. Este recurso é possível com o comando "eval". Abaixo é mostrado um exemplo de código que não usa e outro que usa a metaprogramação.
Na função abaixo, são feitas duas comparações a cada iteração do loop:
Usando metaprogramação, primeiro seria montando o código que desejamos executar, depois passariamos para que ele seja avaliado com "eval":
O segundo código tende a ser mais rápido pois na variável $codigo serão colocadas apenas as instruções desejaveis de serem realizadas durante o loop. Se forem passados os valores true e true para $somar e $multiplicar, então o código gerado na variável $codigo seria:
Note que o loop não apresenta condições internamente, o que tornaria a iteração mais rápida.
Entretanto, trabalhar com metaprogramação não é recomendado para otimizar tudo. Pode ser utilizado em códigos de caixa preta, onde a implementação não costuma ser consultada, ou em trechos onde a performance precisa ser muito alta. Escrever um código e jogá-lo em uma variável é uma tarefa arriscada, já que o interpretador só conseguirá detectar erros de sintaxe no código gerado no momento em que o mesmo é avaliado (com o comando "eval"). Observe que isso incluem os delimitadores de instruções (ponto e vírgula), e tudo mais.
A metaprogramação torna o código menos legível e, por isso, também deve ser muito bem pensada antes de ser usada. Porém, abre brecha para construção de estruturas bastante interessantes. Observe o código abaixo:
Este código imprime números de 0 a 9, só que o código também quer aproveitar as iterações do loop para checar se um determinado elemento foi impresso ou não. Assim que o elemento é encontrado, não é mais necessário checar nas próximas iterações. Logo, o código que guarda a busca passa a guardar nada. Quando uma string vazia é passada para "eval", nada é feito.
No exemplo, uma variável guardou um código capaz de mudar o seu próprio valor quando avaliado. Ela poderia mudar o código para outra coisa diferente de uma string vazia. Percebe o quanto a metaprogramação é complexa?
Mas a linguagem também permite que um script consiga alterar seu próprio comportamento em tempo de execução. Isso pode ser útil para otimizar trechos de código. Este recurso é possível com o comando "eval". Abaixo é mostrado um exemplo de código que não usa e outro que usa a metaprogramação.
Na função abaixo, são feitas duas comparações a cada iteração do loop:
/** * Funcao de exemplo * @param array[int] $vetor Vetor de numeros * @param bool $somar Indica se o elemento do vetor deve ser somado com 1 * @param bool $multiplicar Indica se o elemento do vetor deve ser multiplicado por 2 * @return void */ function exemplo($vetor, $somar, $multiplicar) { foreach ($vetor as $elemento) { if ($somar) { $elemento += 1; } if ($multiplicar) { $elemento *= 2; } echo $elemento; } }
Usando metaprogramação, primeiro seria montando o código que desejamos executar, depois passariamos para que ele seja avaliado com "eval":
/** * Funcao de exemplo * @param array[int] $vetor Vetor de numeros * @param bool $somar Indica se o elemento do vetor deve ser somado com 1 * @param bool $multiplicar Indica se o elemento do vetor deve ser multiplicado por 2 * @return void */ function exemplo($vetor, $somar, $multiplicar) { $codigo = 'foreach ($vetor as $elemento) {'; if ($somar) { $codigo .= '$elemento += 1;'; } if ($multiplicar) { $codigo .= '$elemento *= 2;'; } $codigo .= 'echo $elemento;'; $codigo .= '}'; // Executar o codigo gerado dinamicamente eval($codigo); }
O segundo código tende a ser mais rápido pois na variável $codigo serão colocadas apenas as instruções desejaveis de serem realizadas durante o loop. Se forem passados os valores true e true para $somar e $multiplicar, então o código gerado na variável $codigo seria:
foreach ($vetor as $elemento) { $elemento += 1; $elemento *= 2; echo $elemento; }
Note que o loop não apresenta condições internamente, o que tornaria a iteração mais rápida.
Entretanto, trabalhar com metaprogramação não é recomendado para otimizar tudo. Pode ser utilizado em códigos de caixa preta, onde a implementação não costuma ser consultada, ou em trechos onde a performance precisa ser muito alta. Escrever um código e jogá-lo em uma variável é uma tarefa arriscada, já que o interpretador só conseguirá detectar erros de sintaxe no código gerado no momento em que o mesmo é avaliado (com o comando "eval"). Observe que isso incluem os delimitadores de instruções (ponto e vírgula), e tudo mais.
A metaprogramação torna o código menos legível e, por isso, também deve ser muito bem pensada antes de ser usada. Porém, abre brecha para construção de estruturas bastante interessantes. Observe o código abaixo:
$busca = 'if ($i == $elemento) { $achou = true; $busca = ""; }'; $elemento = 7; for ($i = 0; $i < 10; $i++) { eval($busca); echo $i; }
Este código imprime números de 0 a 9, só que o código também quer aproveitar as iterações do loop para checar se um determinado elemento foi impresso ou não. Assim que o elemento é encontrado, não é mais necessário checar nas próximas iterações. Logo, o código que guarda a busca passa a guardar nada. Quando uma string vazia é passada para "eval", nada é feito.
No exemplo, uma variável guardou um código capaz de mudar o seu próprio valor quando avaliado. Ela poderia mudar o código para outra coisa diferente de uma string vazia. Percebe o quanto a metaprogramação é complexa?
comentários (0)
suspender
Lista de Respostas:
09/03/2011 11:13am
(~13 anos atrás)
(~13 anos atrás)
eu não sei pq o pessoa fica negativando um material tão importante como esse que o rubens nos passou...
é importante conhecermos um pouco sobre metaprogramação em PHP...
Valeu pelo FAQ Rubens... Parabéns!
é importante conhecermos um pouco sobre metaprogramação em PHP...
Valeu pelo FAQ Rubens... Parabéns!