5
$a=array('a','b','c','d');

while(key($a)!==NULL){
  echo key($a).'=>'.current($a).'<br/>';
  next ($a);
}

prev($a);
var_dump(current($a));

Why does var_dump return false instead of "d" ?

2
  • I'm guessing once you're gone pat the end of the array, prev will no longer work. Not sure though. Commented May 22, 2012 at 6:54
  • @Corbin I expect you're right, although unsurprisingly the PHP devs haven't deigned to mention that in the documentation... Commented May 22, 2012 at 7:02

2 Answers 2

4

It's definitely by design, and though I've combed through the PHP documentation, I can find no reference to the fact that once you invalidate the pointer by means of nexting past the end of the array you can no longer use prev, the PHP source code (zend_hash.c) makes it clear what's going on:

ZEND_API int zend_hash_move_forward_ex(HashTable *ht, HashPosition *pos)
{
    HashPosition *current = pos ? pos : &ht->pInternalPointer;

    IS_CONSISTENT(ht);

    if (*current) {
        *current = (*current)->pListNext;
        return SUCCESS;
    } else
        return FAILURE;
}

ZEND_API int zend_hash_move_backwards_ex(HashTable *ht, HashPosition *pos)
{
    HashPosition *current = pos ? pos : &ht->pInternalPointer;

    IS_CONSISTENT(ht);

    if (*current) {
        *current = (*current)->pListLast;
        return SUCCESS;
    } else
        return FAILURE;
}

As you can see, the zend_hash_move_backwards_ex (which, in PHP, is mapped to prev) tests whether or not the current pointer is valid before doing anything, and zend_hash_move_forward_ex will set the value to pListNext which is going to be null in case of the last element.

i.e. unlike you might expect, next and prev do not just blindly increment or decrement a C pointer then check the result to return the value or NULL, they actually check the pointer before incrementing or decrementing.

This is definitely a flaw in the documentation and certainly needs to be documented. As mentioned in another reply, you can use end to go to the last element after a pointer has been invalidated by looping over the list.

However, you should be able to implement the logic you want (without having to use end()) by cloning the pointer before each progression and then using the cloned pointer after reaching the end of the array. (but there's no really good reason to do this if you already know prev() is broken by design in terms of backwards navigation of an already-iterated array)

(Off-topic: I'm glad to see the respected PHP tradition of using inconsistent function names is alive and well even in the underlying C code: zend_hash_move_forward_ex vs zend_hash_move_backward*s*_ex.)

Sign up to request clarification or add additional context in comments.

Comments

0
$a=array('a','b','c','d');

while(key($a)!==NULL){
  echo key($a).'=>'.current($a).'<br/>';
  next ($a);
}

prev($a);
var_dump(current($a));

in this code next return the next value and advance to the next point and at the end of the loop it gives the last element but pointer advance to next ie null. so your var_dump(current($a)); retunrs false

but

$a=array('a','b','c','d');

while(key($a)!==NULL){
  echo key($a).'=>'.current($a).'<br/>';
  next ($a);
}

//prev($a);
end(($a);
var_dump(current($a));

you will get your desired element d as it points to the last element d

2 Comments

I think the OP realizes that, the real question is why can you not use prev after next reaches the end of the array.
I have explained about why he is getting false value

Your Answer

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.