在 PHP 中在运行时删除函数(不带 runkit 扩展)

2022-08-30 15:41:21

我知道这个问题看起来很笨拙和奇怪,但是有没有办法在PHP中在运行时删除函数?

我有一个在“if”块中声明的递归函数,并希望该函数仅在该“if”块中“有效”。我不希望这个函数被调用到这个块之外。

我发现runkit_function_removerunkit没有在我的Web主机上启用。还有别的方法可以做到这一点吗?

顺便说一句,我只支持PHP 5.1.0。

编辑:我知道我的问题很棘手,但这是我想做的确切事情:

if (function_exists('get_magic_quotes_gpc') && @get_magic_quotes_gpc())
{
    function stripslashes_deep($value)
    {
        return is_array($value) ? array_map('stripslashes_deep', $value) : stripslashes($value);
    }

    $_POST = array_map('stripslashes_deep', $_POST);
    $_GET = array_map('stripslashes_deep', $_GET);
    $_COOKIE = array_map('stripslashes_deep', $_COOKIE);
    $_REQUEST = array_map('stripslashes_deep', $_REQUEST);

    //runkit_function_remove('stripslashes_deep');
}

由于“stripslashes_deep”只有在Magic Quotes打开时才会存在,因此我想在完成它时摆脱它。我不希望人们依赖一个并不总是存在的功能。我希望现在更清楚了。也欢迎非黑客解决方案建议!


答案 1

来自 PHP 手册中关于用户定义函数的:

PHP中的所有函数和类都具有全局作用域 - 它们可以在函数外部调用,即使它们是在函数内部定义的,反之亦然。[...]PHP 不支持函数重载,也无法取消定义或重新定义以前声明的函数。

例外情况是通过 。但是,您可以将函数定义为匿名函数,并在运行后将其取消设置,例如runkit

if (function_exists('get_magic_quotes_gpc') && @get_magic_quotes_gpc()) {
    $fn = create_function('&$v, $k', '$v = stripslashes($v);'); 
    array_walk_recursive(array(&$_GET, &$_POST, &$_COOKIE, &$_REQUEST), $fn);
    unset($fn);
}

一些评论者正确地指出(但现在在PHP中不再是问题),你不能在内部调用一个匿名函数。通过使用,您可以绕过此限制。就个人而言,我只会创建一个常规函数,而不会费心删除它。它不会伤害任何人。只需给它一个适当的名称,如.array_walk_recursivestripslashes_gpc_callback

注意:在注释后进行编辑和压缩


答案 2

从 PHP 5.3 开始,您可以使用匿名函数:

$anonymous_function = function($value){
  // do stuff
};

这样称呼它:

$returned_value = $anonymous_function('some parameter');

要删除该函数,只需取消设置变量:

unset($anonymous_function);

下面是如何实现函数的示例:

$stripslashes_deep = function (&$object){
  global $stripslashes_deep;
  if(is_array($object)) 
    foreach($object as &$value){ 
      if(is_array($value)) 
        $stripslashes_deep($value);
      else
        $value = stripslashes($value);
    }
};

匿名函数没有名称。因此,您不能使用array_map,因为它只会将函数名称作为参数。

匿名函数具有变量作用域。因此,您必须将包含该函数的变量声明为全局变量,以便从递归函数中访问它。

遗憾的是,如果在匿名函数中定义了一个常规函数,则即使在取消设置变量后,它也将是全局可用的。(我真的看不出这样做的好处。我希望这是一个错误,以后可以纠正:-)


推荐