PHP 5.2 出现的Nesting level too deep - recursive dependency问题

本文解决从PHP5.1升级到PHP5.2后遇到的Nestingleveltoodeep-recursivedependency错误。通过使用严格比较运算符(===)而非==(非严格比较),可以避免因对象间递归比较导致的错误。
在PHP 5.1下运行很好的PHP,移植到PHP5.2之后出现 Nesting level too deep - recursive dependency的问题。
对PHP我是不懂了,但让其正常运行是我的责任,于是google。
下面是找到的东西

http://www.phpdeveloper.org/news/6691

So, you've just upgraded to PHP 5.2 and all is going well until you come across a page in your application that gives the message "Nesting level too deep - recursive dependency?". With such a vague error message, you might have trouble locating the source of the problem. Thankfully, someone's already been there and figured out the issue - Richard Lord.
I installed PHP 5.2 on one of my testing servers today and a couple of bits of code that previously worked fine in version 5.1.6 threw fatal errors in the new version. The error message was "Nesting level too deep - recursive dependency?" and it took a little time to track down the root of the problem. Here's what I'd done wrong.

Basically, his problem was using the "non-strict" evaluation for checking if two objects were equal to each other (== instead of ===). This compares everything about them, down to the properties - even if they're references to other properties inside of the same class (which is where the problem lies).

So, the fix is simple - === instead of == when comparing those objects. You'll be happier for the change.


 

http://www.bigroom.co.uk/blog/php-nesting-level-too-deep-recursive-dependency/


I installed PHP 5.2 on one of my testing servers today and a couple of bits of code that previously worked fine in version 5.1.6 threw fatal errors in the new version. The error message was “Nesting level too deep - recursive dependency?” and it took a little time to track down the root of the problem. Here’s what I’d done wrong.

In PHP there are two comparison operators, == and ===. It’s generally known that the first is not strict about type but the second is. So, for example

echo ( false == 0 ); // true
echo ( false === 0 ); // false
    - 0 is an integer and false is a boolean

My problem arose from using non-strict typing with objects.

$a = new MyObj();
$b = new MyObj();
if( $a == $b )

I hadn’t considered what I was doing with this code. When comparing two objects using the non-strict comparison operator (==) PHP compares all the properties of the objects and if they match the objects are deemed to be equal. If they don’t match they are not equal. In effect, we have a recursive comparison of all the properties of each object, and all their properties, etc. until we reach basic data types like strings and integers.

If, however, we use strict comparison (===), PHP will check whether the two objects are exactly the same object, not just objects with the same properties.

class MyObj
{
    public $p;
}

$a = new MyObj();
$b = new MyObj();
$c = new MyObj();
$a->p = 1;
$b->p = 1;
$c->p = 2;
echo ( $a == $c ); // false
echo ( $a == $b ); // true
echo ( $a === $b ); // false

The problem arises if you have circular references in your objects properties. So, for example

class MyObj
{
    public $p;
}
class OtherObj
{
    public $q;
}

$a = new MyObj();
$b = new OtherObj();
$a->p = $b;
$b->q = $a; // the circular reference: $a->p->p === $a

$c = new MyObj();
$d = new OtherObj();
$c->p = $d;
$d->q = $c;// another circular reference: $c->p->p === $c

echo ( $a == $c ); // Fatal error:
    Nesting level too deep - recursive dependency?

In order to compare $a to $c, PHP must compare their properties. So the logic in PHP goes something like this: $a == $c if $a->p == $c->p if $a->p->p == $c->p->p if $a->p->p->p == $c->p->p->p etc. indefinitely.

PHP 5.1 seemed to smooth over the problem somehow (probably after a certain level of recursion it simply returned false) - and usually it worked out fine. PHP 5.2 correctly produces the fatal error above.

Once you know the problem, the solution is easy - use strict comparison.

echo ( $a === $c ); // false (and no error)

The strict comparison will simply check whether the two objects are at the same location in memory and so doesn’t even look at the values of the properties.

N.B. The same problem can arise when using the negated comparison operators (use !== instead of !=) and when using in_array (use in_array’s third parameter to indicate strict comparison).


总之问题是解决了,是因为语言不规范所致。将==转为===, 将!=转为!==,彻底好了。

在使用 Spyglass 工具进行代码质量分析时,工具会针对代码中 if-else 结构嵌套层级超过 5 层的情况生成警告或错误信息。这种检查通常属于代码复杂度管理的一部分,目的是为了提高代码的可读性和可维护性。深层嵌套的 if-else 语句会使代码难以理解,同时增加调试和修改的难度。 为了解决这个问题,可以采取以下几种方法: 1. **重构条件逻辑**:可以通过提取条件判断逻辑到单独的函数或方法中,以减少嵌套层级。例如,将某些条件判断封装成布尔函数,这样可以将复杂的 if-else 结构简化。 ```python def is_condition_met(data): return data > 0 and data < 10 # 示例条件 if is_condition_met(some_data): # 执行操作 ``` 2. **使用卫语句(Guard Clauses)**:通过提前返回来减少嵌套。当遇到不需要继续执行的情况时,立即返回,而不是将整个逻辑包裹在 if 语句内部。 ```python def check_data(data): if data <= 0: return False if data >= 10: return False # 主要逻辑 return True ``` 3. **策略模式**:对于复杂的条件分支,可以考虑使用策略模式,将不同的条件分支转换为不同的策略对象,从而避免大量的 if-else 判断。 ```python class StrategyA: def execute(self): # 实现细节 class StrategyB: def execute(self): # 实现细节 def context(strategy): strategy.execute() # 根据条件选择策略 if some_condition: context(StrategyA()) else: context(StrategyB()) ``` 4. **多态替代条件分支**:如果条件判断是基于类型或其他固定规则,可以考虑使用面向对象的设计原则,如多态性来替代条件分支。这不仅可以减少 if-else 的使用,还能提高代码的扩展性和灵活性。 5. **配置化处理**:对于某些可以通过配置决定的行为,可以将这些行为的决策过程移到配置文件中,从而避免硬编码的 if-else 结构。 6. **异常处理**:在某些情况下,使用异常处理机制代替传统的 if-else 流程控制,可以使得代码更加清晰简洁。不过需要注意的是,异常处理不应该被滥用,仅适用于真正异常的情况。 7. **文档和注释**:虽然这不是解决深层嵌套的根本方法,但是良好的文档和注释可以帮助其他开发者更快地理解复杂的逻辑结构,从而间接提升代码质量。 通过以上方法的应用,可以在很大程度上缓解由深层 if-else 结构带来的问题,同时也能够满足 Spyglass 工具对代码质量的要求。[^1]
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值