1

SO,

I have an issue with determining recursion in arrays in PHP. Assume that I have a dynamic-generated array, which finally can looks like:

$rgData = [
 ['foo', 'bar', $rgTemp=[7, 31, true]],
 [-5, &$rgData, 'baz']
];

(links to variables here are provided dynamically and may refer to an array itself). Another sample:

$rgData = [
 ['foo', 'bar', $rgTemp=[7, 31, true]],
 [-5, &$rgTemp, 'baz']
]; 

Both arrays have some references inside, but second looks good since it's reference is not cycled. Later, due to my logic, I have to handle array via recursive functions (something like array_walk_recursive) - and, of cause, I got Fatal error due to infinite nested array recursion in case of first sample above.

My question is - how to determine if an array has infinite recursion. Note, that this question is more complicated than simple search link from inside array to itself, because we can have something like:

$rgOne = [
 ['foo', 'bar'],
 ['baz']
];
$rgTwo = [6, 'test', &$rgOne];
$rgOne[1][] = &$rgTwo;

i.e. more complicated recursion. I found that PHP can resolve this somehow in var_dump and similar functions - for example, dump of the third sample will look like:

array(2) {
 [0]=>
 array(2) {
 [0]=>
 string(3) "foo"
 [1]=>
 string(3) "bar"
 }
 [1]=>
 array(2) {
 [0]=>
 string(3) "baz"
 [1]=>
 &array(3) {
 [0]=>
 int(6)
 [1]=>
 string(4) "test"
 [2]=>
 &array(2) {
 [0]=>
 array(2) {
 [0]=>
 string(3) "foo"
 [1]=>
 string(3) "bar"
 }
 [1]=>
 *RECURSION*
 }
 }
 }
}

i.e. *RECURSION* was caught. Currently, I've tried to resolve a matter via function:

function isLooped(&$rgData, &$rgCurrent=null)
{
 foreach($rgData as $mKey=>$mValue)
 {
 if(is_array($mValue) && isset($rgCurrent) && 
 $rgCurrent===$rgData /* that's where, it seems, I need help*/)
 {
 return true;
 }
 elseif(is_array($mValue) && isLooped($mValue, $rgData))
 {
 return true;
 }
 }
 return false;
}

but with no success (and I know why - that comparison is invalid). The only idea I have now is to do weird thing, like:

function isLooped(&$rgData)
{
 $rgTemp = @var_export($rgData, 1);
 return preg_match('/circular references/i', error_get_last()['message']);
}

but that is sad since I need at least copy my array data to some temporary storage (and, besides, all of this looks like a glitch, not a proper solution). So, may be there are some ideas of how to do that normal way?

Update: I've found a solution via changing key in the array and then looking for it in recursive loop. This is much better than var_* functions, but still not exactly what I want. Is there a way to do this without var_* functions or changing original array?

asked Aug 26, 2013 at 9:21
3
  • This is similar to the question you are asking stackoverflow.com/questions/9042142/… Commented Aug 26, 2013 at 9:33
  • @VladimirHraban I'm not sure - since I've mentioned that I don't want to rely on print_r/var_dump e.t.c - functions. Another solution there is to change array itself (and check again then) - this looks better but still not enough to answer: is it possible to do normal way or not (negative answer is also good for me - I'll know that it's simpler to change architecture itself). Thanks! Commented Aug 26, 2013 at 9:39
  • possible duplicate of Reference detection in array from another function Commented Aug 26, 2013 at 10:50

1 Answer 1

1

The problem is that PHP doesn't have a mechanism to tell you whether two variables reference the same zval (internal data type representing the actual held data). This rules out keeping track of the variables you have traversed so far as a solution.

Without this feature or modifying elements (pin method) it's unfortunately not possible to detect a recursive data structure except for var_dump() or print_r() hacks.

answered Aug 26, 2013 at 11:08
2
  • So, it seems, that the answer I'm looking for (i.e. "No, this can't be done with such conditions"). Thanks. Commented Aug 26, 2013 at 11:11
  • Suddenly :p Only one my question on SO was resolved positive :p (and solution to it I've implemented myself) Commented Aug 26, 2013 at 11:57

Your Answer

Draft saved
Draft discarded

Sign up or log in

Sign up using Google
Sign up using Email and Password

Post as a guest

Required, but never shown

Post as a guest

Required, but never shown

By clicking "Post Your Answer", you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.