How does the current function work?

19
It's been a while since I've always used the current() function in PHP to get the first element of the array (which in fact is not its functionality since it returns the current pointer in array is) and I've been noticing something that has left me a bit confused compared to the features of next() , prev() and reset() .

And I explain why.

In PHP manual and even in Notepad ++ , we see that the argument of current() is a reference passage of an element of type array , in the same way as next() and prev() . In fact, the function declaration is this:

mixed current ( array &$array )

However, if you use it in a array returned function or even a temporary array (in this case, declared directly as current() argument) works normally (the argument would be a variable passed by reference).

current([1, 2, 3]);// 1
current(explode(',', '1, 2, 3')); //1
$array = [1, 2, 3];
current($array); //1

Now, what makes my confusion even greater is that if I pass a array directly into functions like next() and prev() , this causes a fatal error:

next([1, 2, 3]);
//Fatal error: Only variables can be passed by reference
echo next(explode(',', '1, 2, 3')); 
//Strict Standards: Only variables should be passed by reference

The question is: If the PHP manual specifies in the function declaration that current() works with arrays passed by reference (like many other functions used for arrays ), why is it the only one that works with arrays passed directly as an argument (as in the first example)?

Note : The PHP Manual is very emphatic: mixed current ( array &$array )

    
asked by anonymous 10.07.2014 / 13:57

4 answers

1

After a long time and even forgetting this question, I found the PHP staff response .

If I do not understand the answer very well, help by editing it.

According to such a [email protected] :

  

Non-iterator objects are iterable like arrays, mostly for BC reasons.   This is expected behavior, but I do not think we should change the   manual page to note that - effectively, it will be treated like an array   regardless, and it's confusing.

Translating is (google translator):

  

Non-iterator objects are iterated as arrays, mainly   for reasons of reverse compatibility. This behavior is expected but I do not think we   we should change the manual page. Note that he   will be treated as an array anyway, and this is confusing.

    
31.07.2015 / 17:47
12

Because there is no need to pass it by reference, the only thing this function does is to return the contents of the current pointer of the array, and this will not modify the array, so it is not necessary to pass it by reference.

Other examples of current() and other functions of the same thread:

$transport = array('foot', 'bike', 'car', 'plane');
$mode = current($transport); // $mode = 'foot';
$mode = next($transport);    // $mode = 'bike';
$mode = current($transport); // $mode = 'bike';
$mode = prev($transport);    // $mode = 'foot';
$mode = end($transport);     // $mode = 'plane';
$mode = current($transport); // $mode = 'plane';

$arr = array();
var_dump(current($arr)); // bool(false)

$arr = array(array());
var_dump(current($arr)); // array(0) { }

Note that all functions simply return and modify the pointer.

As for the error you generated when trying to apply next() to the array declaration, it is because these functions were made to work with the array pointer.

But if you try to declare the array inside the function, the pointer does not exist, so it generates the error you posted in the question.

Pointer is directly linked to the creation of the variable of type array, it is the index of the variable, which only exists from the moment you declare it.

The manual informs you that the array is passed by reference:

mixed current ( array &$array )

This is because when we use functions of this "group", such as next() , it changes the position of the pointer, ie it is not necessary to pass by reference, because the function itself does this by changing the pointer position ex. :

$var = array(1,2,3);
echo current($var);//1
echo next($var);//2  <- Alterou o ponteiro de $var
echo current($var);//2 
$a = $var; // <- Copiou o array
echo current($a); //2 <- Ponteiro na mesma posição de $var.

Pass by reference: link

Function current(): link

    
10.07.2014 / 14:16
11

By observing the behavior described by you it is clear that this must be an error in the php manual. My suspicion is that since php uses the Copy-On-Write technique, it only generates an error when the pointer ( referencia ) of the array is modified. Home In the case of the current function, php is not changing the value of the pointer, just returning its position.

I think it's interesting to open a bug-report in php and ask them to add a note to the manual to make the function more clear.

    
02.02.2015 / 15:43
7

I do not think the manual is wrong, just incomplete. I'm not familiar enough with the PHP source to crawl the problem to the point where the error message is issued , but I think I understand what happens.

The problem is not whether or not we have a reference; as the function is defined with &$array as parameter, the argument it receives is always a reference to the last array. I believe you are emphasizing the wrong part of the error message:

  

Only variables can be passed by reference

The key here is only variables , not passed by reference . In next([1, 2, 3]); , you do not pass a variable, it passes a literal array. There is no reference to it outside the scope of the next function; once it returns, the reference count of the structure representing the array will be 0 , and the memory becomes collectible by the "junk".

It does not make sense for the functions that move the array pointer to change the state of an object that will no longer exist once they return. Moving the pointer is a dispensable operation, and they have a guard against it somewhere (I'm not sure where, but if you look at the source code they differ in one or two lines - examples: next and current ). There are even tests to ensure that this usage generates an error ( example ).

Notice that the error does not occur if the array is assigned to a variable, and the variable is passed to the function:

next($var = [1, 2, 3]);

In this case, $var exists in the scope where the function was called, ie remains available after the call and can not be claimed by the garbage collector .

When you take the current value with current , this does not change the state of the array; in this case, PHP sees no problems and lets pass. Within my limitations of knowledge regarding the details of implementation of PHP, this is the evaluation that I was able to do. Maybe I'm wrong, if anyone has evidence of this please let me know.

    
07.02.2015 / 04:21