【发布时间】:2021-12-21 08:54:53
【问题描述】:
我正在尝试在 PHP 中实现我自己的序列化/var_dump 样式函数。如果有循环数组的可能性(确实存在),这似乎是不可能的。
在最近的 PHP 版本中,var_dump 似乎可以检测到循环数组:
php > $a = array();
php > $a[] = &$a;
php > var_dump($a);
array(1) {
[0]=>
&array(1) {
[0]=>
*RECURSION*
}
}
我将如何在 PHP 中实现我自己的序列化类型的方法来进行类似的检测?我不能只跟踪我访问过的数组,因为 PHP 中数组的严格比较对于包含相同元素的不同数组返回 true,并且比较循环数组会导致致命错误,无论如何。
php > $b = array(1,2);
php > $c = array(1,2);
php > var_dump($b === $c);
bool(true)
php > $a = array();
php > $a[] = &$a;
php > var_dump($a === $a);
PHP Fatal error: Nesting level too deep - recursive dependency? in php shell code on line 1
我一直在寻找一种方法来查找数组的唯一 ID(指针),但我找不到。 spl_object_hash 仅适用于对象,不适用于数组。如果我将多个 不同 数组转换为对象,它们都会得到相同的 spl_object_hash 值(为什么?)。
编辑:
在每个数组上调用 print_r、var_dump 或序列化,然后使用某种机制来检测这些方法检测到的递归的存在是算法复杂性的噩梦,并且基本上会使任何使用都太慢而无法在大型嵌套数组上实用。
接受的答案:
我接受了下面的答案,这是第一个建议临时更改一个数组以查看它是否确实与另一个数组相同的答案。这回答了“我如何比较两个数组的身份?”从中递归检测是微不足道的。
【问题讨论】:
-
答案是:你不能。见check if object/array is a reference。不可能进行类似指针的引用比较,因此也不可能检测到循环。在您的情况下,更好的解决方法可能是通过本机函数之一 (
json_decode(json_encode())) 将其转换为摆脱引用,然后才应用您自己的序列化。 -
现在甚至 PHPUnit 都在使用临时“标记”方法来检测数组递归。
标签: php arrays recursion identity circular-reference