vifito.eu

Web Development & Open Source

  • Aumentar o tamaño da fonte
  • Tamaño do texto por defecto
  • Diminuir o tamaño do texto

Redefinir funcións en PHP

Supoñamos que no noso programa hai unha función definida e que o código avaliado contén unha que se chame igual. Qué sucedería? Cómo resolverlo?

Se temos nun ficheiro definida unha función co nome "foo()", ao executar o codigo, sen ter en conta ningunha modificación, a mensaxe de erro que obtemos será similar a seguinte:

Fatal error: Cannot redeclare foo() (previously declared in.... 

Para facer unha proba creamos un ficheiro como o seguinte:

<?php
error_reporting(E_ALL);
################################################################################
function foo() {
echo "Funcion foo orixinal" . PHP_EOL;
}
// Invocamos foo()
foo();
################################################################################

$code =<<< PHPCODE
function foo() {
echo "Funcion foo dende eval" . PHP_EOL;
}
PHPCODE;

// Tentamos avaliar $code
eval($code); // Fatal error: Cannot redeclare foo() (previously declared in...


Ao estar definida unha función co mesmo nome, en tempo de execución, ao procesar o código da sentencia exec lanza un erro. Un método sinxelo sería comprobar se a función xa está definida con function_exists. Outra posibilidade sería empregar extensións do motor Zend de PHP que permitan a "redefinición" da función (runkit, APD). No seguinte código recóllese un exemplo de uso de runkit para redefinir a función, con runkit_function_redefine:

$code =<<< PHPCODE
if(function_exists('foo')){
// Redefinir a función
runkit_function_redefine('foo', '', 'echo "(runkit version)" . PHP_EOL;');
} else {
function foo() {
echo "Funcion foo dende eval (sen redefinir)" . PHP_EOL;
}
}
PHPCODE;
eval($code) . PHP_EOL;
foo();


Instalación de runkit

Compilación e instalación da extensión runkit en contornos debian/ubuntu.

  • Comprobar que está instalado o paquete php5-dev (en distribucións debian).
  • Descargar os fontes de runkit do repositorio pecl de PHP:
 :~/$ wget http://pecl.php.net/get/runkit-0.9.tgz
  • Descomprimir os fontes de runkit:
:~/$ tar xzvf runkit-0.9.tgz
:~/$ cd runkit-0.9
  • Compilar a extensión PHP (NON executar o comando make install):
:~/$ phpize
:~/$ ./configure
:~/$ make
  • Se aparece algunha mensaxe de erro ao executar o comando make é posible que sexa por culpa dun bug nas versións de PHP 5.2.x . Para correxir este bug hai que facer uns cambios no ficheiro fonte runkit_import.c
// Cambiar esta liña
zend_unmangle_property_name(key, &cname, &pname);
// por esta outra
zend_unmangle_property_name(key, key_len, &cname, &pname);
  • Instalar a extensión copiando runkit.so ao directorio de extensións de PHP, indicarlle a PHP que cargue a extensión e reiniciar apache.
// Averiguar a ruta ao directorio de extensións de PHP
:~# php -r "phpinfo();" | grep extension_dir
extension_dir => /usr/lib/php5/20060613+lfs => /usr/lib/php5/20060613+lfs
:~# sudo cp .libs/runkit.so /usr/lib/php5/20060613+lfs/
:~# echo "extension=runkit.so" > /etc/php5/conf.d/runkit.ini
:~# apache2ctl restart
  • Unha vez reiniciado o servidor Apache2 xa teremos a nosa disposición a extensión runkit.


Redefinición de funcións en PHP 5.3

O uso de namespaces na versión 5.3 de PHP permite a definición dunha función nun espazo de nomes distinto non provocará colisións coa definida noutro.

namespace CDWA\PHP {
$foo = function() {echo "Funcion en namespace CDWA\\PHP" . PHP_EOL;};
$foo(); // A do namespace
\foo(); // A orixinal
}