Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

PHP's current() & key() functions; inconsistent with function signature

I've noticed that PHP's current() and key() array functions (like other array-pointer functions) take the array argument by reference:

mixed current ( array &$array )
Every array has an internal pointer to its "current" element, which is initialized to the first element inserted into the array.

After a few quick checks, it appears that both current() and key() (unlike other array-pointer functions) accept the array argument by value, thereby not throwing an error when passed the return value of a function.

I've concluded that it's simply because current() and key() do not try to move the array pointer, and therefore do not require the argument be passed by reference (or do so in some transparent, quiet, secretive way). However, this is of a bit of concern to me.

Can anyone confirm if this is the intended functionality? I'd gladly use it to snatch up the first element/key of a returned array, but it seems awfully strange that PHP is allowing this when under nearly any other circumstance a fatal error (or strict standards warning) is issued for passing values to a by-reference parameter.

Feature or bug?


For instance:

error_reporting(-1);

function getArray(){
    return array('a', 'b', 'c');
}

var_dump( current(getArray()) );
var_dump( key(getArray())     );
var_dump( next(getArray())    );
var_dump( prev(getArray())    );
var_dump( reset(getArray())   );
var_dump( end(getArray())     );

Results:

string(1) "a"

int(0)

Strict standards: Only variables should be passed by reference ...
string(1) "b"

Strict standards: Only variables should be passed by reference ...
bool(false)

Strict standards: Only variables should be passed by reference ...
string(1) "a"

Strict standards: Only variables should be passed by reference ...
string(1) "c"
like image 652
Dan Lugg Avatar asked Nov 05 '22 16:11

Dan Lugg


1 Answers

That's definitely a feature, and I would not want to live without it.

Now the question is if the documentation is correct about the &.

The code

current

PHP_FUNCTION(current)
{
    HashTable *array;
    zval **entry;

    if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "H", &array) == FAILURE) {
        return;
    }

    if (zend_hash_get_current_data(array, (void **) &entry) == FAILURE) {
        RETURN_FALSE;
    }
    RETURN_ZVAL(*entry, 1, 0);
}

next

PHP_FUNCTION(next)
{
    HashTable *array;
    zval **entry;

    if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "H", &array) == FAILURE) {
        return;
    }

    zend_hash_move_forward(array);

    if (return_value_used) {
        if (zend_hash_get_current_data(array, (void **) &entry) == FAILURE) {
            RETURN_FALSE;
        }

        RETURN_ZVAL(*entry, 1, 0);
    }
}

Conclusion

The docs are correct - the array is taken as reference in both cases.

No idea though why on throws the error, the other not.

Btw, the errors are thrown in

  • Zend/zend_vm_def.h
  • Zend/zend_vm_execute.h
like image 193
cweiske Avatar answered Nov 09 '22 15:11

cweiske