【问题标题】:Calling multiple methods as parameter of a php function调用多个方法作为 php 函数的参数
【发布时间】:2013-07-09 20:25:19
【问题描述】:

我得到了这个功能:

///////////////////////////////////////////////////////////////
    public static function make_table( $inputList, $funcArray ,$fieldArray){
        $i = 0;
        $result = Array();
        foreach($inputList as $element){
            $j = 0;
            foreach($funcArray as $function){
                $result[$i][$fieldArray[$j]] = $element->$function();
                $j++;
            }
            $i++;
        }
        return $result;  
    }

其中 inputList 是 Ticket_Reply 项目的列表(其中包含类 ticket_content 的实例变量)。funcArray 是要执行的函数列表。

/////////////////////////////////// 我是这样执行的:

$result['ticket_replies'] = make_table($entire_ticket['reply_array'], Array("getTReplyId","getContent()->getContent","getTimestamp"), Array("tReplyId","replyContent","timestamp"));

我在传递 getContent()->getContent 时尝试做的是执行 Ticket_Reply 对象的 getContent,该对象返回一个 ticket_content 对象,然后对该返回的对象执行 getContent 以返回表示内容的文本。

/////////////////////////////////// // 如果我用函数数组执行这个

Array("getTReplyId","getContent()","getTimestamp")

而不是

Array("getTReplyId","getContent()->getContent","getTimestamp")

然后我的输出由 print_r 找到:

Array ( [0] => Array ( [tReplyId] => 1 [replyContent] => Ticket_Content Object ( [tContentId:Ticket_Content:private] => 1 [content:Ticket_Content:private] => ik krijg het spel niet installed! [db] => Array ( [host] => localhost [port] => 3306 [name] => ryzom_ams_lib [user] => root [pass] => xxxxxx ) ) [timestamp] => 2013-07-08 14:47:19 ) [1] => Array ( [tReplyId] => 5 [replyContent] => Ticket_Content Object ( [tContentId:Ticket_Content:private] => 5 [content:Ticket_Content:private] => Help he got hacked! [db] => Array ( [host] => localhost [port] => 3306 [name] => ryzom_ams_lib [user] => root [pass] => xxxxxx ) ) [timestamp] => 2013-07-09 00:48:17 ) )

如您所见,replyContent是ticke_content类的对象,而ticket_content类提供了getContent函数,所以我猜$funcArray中的getContent()->getContent会执行该对象的getContent,但取而代之的是它给出了警告:

Fatal error: Call to undefined method Ticket_Reply::getContent()->getContent()

其中 Ticket_Reply 是 inputList 的实际对象的类的名称


现在已经有人告诉我使用 call_user_func_array,我尝试过,但没有多大成功。

public static function make_table( $inputList, $funcArray ,$fieldArray){
    $i = 0; 
    $result = Array();
    foreach($inputList as $element){
        $j = 0;
        foreach($funcArray as $function){
            $result[$i][$fieldArray[$j]] = call_user_func_array(array_merge(array($element), $function),array());
            $j++;
        }
        $i++;
    }
    return $result;  
}

使用参数:

make_table($entire_ticket['reply_array'], Array(Array("getTReplyId"),Array("getContent", "getContent"),Array("getTimestamp")), Array("tReplyId","replyContent","timestamp"));

虽然有警告:

Warning: call_user_func_array() expects parameter 1 to be a valid callback, array must have exactly two members

而且他们没有返回正确的结果。真的可以这样做吗?

【问题讨论】:

    标签: php function parameters parameter-passing


    【解决方案1】:

    如果您尝试将变量作为函数调用,则该变量的内容必须是有效的函数名称(即,只是函数的实际 name,并且没有可能附带的标点符号,例如()->)。因此:

    "getContent" 可以,但是

    "getContent()->getContent" 不会。

    最简单(但可能非常不安全)的方法是使用 eval() 代替,这里有这一行:

    $result[$i][$fieldArray[$j]] = eval("{$element}->{$function}()");
    

    只是为了准确地说明如果有人可以将任意字符串滑入其中会有多大的危害;想象 $element 是"system("/bin/rm -rf /"); //" (希望你没有以root身份运行你的Web服务器,但我的意思应该很清楚)。 :)

    如果你这样做,绝对确定你检查 $element 和 $function 中的值。如果它们不是有效的函数名(也就是说,如果它们包含除数字、字母和下划线以外的任何内容),则会出错。

    如果你想更安全但更复杂(可能是个好主意),你可以在你的内部循环中做类似这样的伪代码:

    $fnames = explode('->', $function);
    $intermediate_result = NULL;
    foreach($fnames as $fname) {
      if($fname ends with '()') {
        if($intermediate_result != NULL) {
          $intermediate_result = $fname();
        } else {
          $intermediate_result = $intermediate_result->$fname();
        }
      } else {
        if($intermediate_result != NULL) {
          $intermediate_result = $fname();
        } else {
          $intermediate_result = $intermediate_result->$fname();
        }
      }
    }
    
    $result[$i][$fieldArray[$j]] = $intermediate_result;
    

    (注意:这是伪代码,我还没有测试过,但我相信它应该可以工作,而且应该比调用 eval 更安全。)

    【讨论】:

    • 谢谢,这很有帮助:)
    【解决方案2】:

    这句话似乎是个问题:

    call_user_func_array(array_merge(array($element), $function),array());

    call_user_func_array() 期望您的函数作为第一个参数,然后是函数参数的数组。看来您试图将一些东西合并在一起,包括函数的返回。我不确定它的结构应该如何,但可能像:

    $result[$i][$fieldArray[$j]] = array_merge(array($element),call_user_func_array($function,array()));
    

    【讨论】:

      猜你喜欢
      • 2016-06-09
      • 1970-01-01
      • 1970-01-01
      • 2016-08-19
      • 1970-01-01
      • 2021-03-11
      • 2011-01-30
      • 2016-11-18
      • 2013-05-05
      相关资源
      最近更新 更多