【问题标题】:How to get the current recursion level in a PHP function如何在 PHP 函数中获取当前递归级别
【发布时间】:2013-11-24 09:54:15
【问题描述】:

如何获取 PHP 函数中的当前递归级别?

我的意思是,有没有像下面这样的“神奇”(或最终正常)功能?

function doSomething($things) {
    if (is_array($things)) {
        foreach ($things as $thing) {
            doSomething($thing);
        }
    } else {
        // This is what I want:
        echo current_recursion_level();
    }
}

我知道我可以使用另一个函数参数(本例中为$level):

function doSomething($things, $level = 0) {
    if (is_array($things)) {
        foreach ($things as $thing) {
            $level++;
            doSomething($thing, $level);
        }
    } else {
        echo $level;
    }
}

但我想知道是否有内置函数(或技巧)可以做到这一点。可能是debug_backtrace(),但这似乎不是一个简单或快速的解决方案。

我没有找到此信息。也许它根本不存在......

【问题讨论】:

  • 使用静态变量。
  • 检查this

标签: php recursion


【解决方案1】:

你需要自己数数。唯一的选择是 Xdebug 之类的东西,它会描述您的完整软件。但这是非常低效的。

<?php
    function my_recursive_fn($param) {
        static $counter = 0;
        if (is_array($param)) {
            ++$counter;
            foreach ($param as $k => $v) {

            }
        }
        else {
            echo $counter;
            --$counter;

            // If we're returning (only PHP 5.5+)
            try {
                return $counter;
            }
            finally {
                --$counter;
            }
        }
    }
?>

这允许您在没有第二个公共参数的情况下进行计数。

【讨论】:

  • 使用static 是可以的,但是您计算的是数组元素的总数而不是递归级别。要执行后者,只需在函数开头增加变量并在返回之前减少它。
  • 返回之前不需要减少$counter吗?
  • 当然,更正它以真正计算递归。 OP 在循环中有递增。
  • 为什么要递减?该函数实际上被调用了。高度依赖于用例。
  • 因为当你返回时,你不再处于更高的递归级别。并且下次从头开始递归时,递归级别应该再次从 0 开始。
【解决方案2】:
function doSomething($things) {
    static $level = 0;
    if (is_array($things)) {
        foreach ($things as $thing) {
            $level++;
            doSomething($thing);
        }
    }
    else {
        // This is what I want:
        echo $level
    }
}

【讨论】:

  • 恕我直言,您需要在调用函数后减少 $level。
  • 解释一下。例如,想法/要点是什么?请通过editing (changing) your answer 回复,而不是在 cmets 中(without "Edit:"、"Update:" 或类似的 - 答案应该看起来像是今天写的)。
【解决方案3】:

在 Java 中,您可以检查调用堆栈。我认为你可以在 PHP 中做同样的事情:

debug-backtrace 可能就是您要找的那个。

由于 PHP 不使用尾调用优化递归,这应该告诉你递归的深度。

【讨论】:

    【解决方案4】:

    如果你只是想避免达到 PHP 的 100 级递归限制,那么

    count(debug_backtrace()); 
    

    应该足够了。否则,您别无选择传递深度参数,尽管 precrement 运算符使其更清晰,如下例所示。

    function recursable ( $depth = 0 ) {
      if ($depth > 3) {
        debug_print_backtrace();
        return true;
      } else {
        return recursable( ++$depth );
      }
    }
    

    【讨论】:

    • 仅供参考,递归限制不是来自 PHP,而是来自 Xdebug 扩展 xdebug.org/docs/all_settings#max_nesting_level
    • 您能否在答案中限定 100 级递归限制? (但没有“编辑:”、“更新:”或类似的 - 答案应该看起来好像是今天写的。)
    【解决方案5】:
    private function select($modules, $level = 0)
    {
        $return_html = '';
        $level_html = '';
        $new_level = 0;
    
        foreach($modules as $module)
        {
            $repeat = str_repeat('&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;', $level);
    
            if(!empty($module['children']))
            {
                $return_html .= '<option>' . $repeat . ' ' . $module['title'] . '</option>';
    
                $new_level = $level + 1;
    
                $return_html .= $this->select($module['children'], $new_level);
            }
            else
            {
                $return_html .= '<option>' . $repeat . ' ' . $module['title'] . '</option>';
            }
        }
        return $return_html;
    }
    

    【讨论】:

    • 解释一下。例如,想法/要点是什么?请通过editing (changing) your answer 回复,而不是在 cmets 中(without "Edit:"、"Update:" 或类似的 - 答案应该看起来像是今天写的)。
    猜你喜欢
    • 2011-05-18
    • 2018-05-28
    • 1970-01-01
    • 2018-10-20
    • 1970-01-01
    • 2010-11-29
    • 2016-02-09
    • 2015-01-30
    • 1970-01-01
    相关资源
    最近更新 更多