diff options
Diffstat (limited to 'ext/standard/array.c')
-rw-r--r-- | ext/standard/array.c | 97 |
1 files changed, 77 insertions, 20 deletions
diff --git a/ext/standard/array.c b/ext/standard/array.c index 91a8833347..fa19737522 100644 --- a/ext/standard/array.c +++ b/ext/standard/array.c @@ -2563,42 +2563,66 @@ PHP_FUNCTION(array_count_values) } /* }}} */ -/* {{{ proto array array_column(array input, mixed key) - Return the values from a single column in the input array, identified by the key */ +/* {{{ proto array array_column(array input, mixed column_key[, mixed index_key]) + Return the values from a single column in the input array, identified by the + value_key and optionally indexed by the index_key */ PHP_FUNCTION(array_column) { - zval *zarray, *zoffset, **data, **zvalue; + zval *zarray, *zcolumn, *zkey = NULL, **data, **zcolval, **zkeyval; HashTable *arr_hash; HashPosition pointer; - long index = 0; - char *key = NULL; - int key_len = 0; + ulong column_idx = 0, key_idx = 0, keyval_idx = 0; + char *column = NULL, *key = NULL, *keyval = NULL; + int column_len = 0, key_len = 0; - if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "az", &zarray, &zoffset) == FAILURE) { + if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "az|z", &zarray, &zcolumn, &zkey) == FAILURE) { return; } - switch (Z_TYPE_P(zoffset)) { + switch (Z_TYPE_P(zcolumn)) { case IS_NULL: - index = 0; + column_idx = 0; break; case IS_LONG: - index = Z_LVAL_P(zoffset); + column_idx = Z_LVAL_P(zcolumn); break; case IS_STRING: - key = Z_STRVAL_P(zoffset); - key_len = Z_STRLEN_P(zoffset); + column = Z_STRVAL_P(zcolumn); + column_len = Z_STRLEN_P(zcolumn); break; case IS_OBJECT: - convert_to_string(zoffset); - key = Z_STRVAL_P(zoffset); - key_len = Z_STRLEN_P(zoffset); + convert_to_string(zcolumn); + column = Z_STRVAL_P(zcolumn); + column_len = Z_STRLEN_P(zcolumn); break; default: - php_error_docref(NULL TSRMLS_CC, E_WARNING, "The key should be either a string or an integer"); + php_error_docref(NULL TSRMLS_CC, E_WARNING, "The column key should be either a string or an integer"); RETURN_FALSE; } + if (zkey) { + switch (Z_TYPE_P(zkey)) { + case IS_NULL: + key_idx = 0; + break; + case IS_LONG: + key_idx = Z_LVAL_P(zkey); + break; + case IS_STRING: + key = Z_STRVAL_P(zkey); + key_len = Z_STRLEN_P(zkey); + break; + case IS_OBJECT: + convert_to_string(zkey); + key = Z_STRVAL_P(zkey); + key_len = Z_STRLEN_P(zkey); + break; + default: + php_error_docref(NULL TSRMLS_CC, E_WARNING, "The index key should be either a string or an integer"); + RETURN_FALSE; + } + } + arr_hash = Z_ARRVAL_P(zarray); array_init(return_value); @@ -2607,14 +2631,47 @@ PHP_FUNCTION(array_column) zend_hash_move_forward_ex(arr_hash, &pointer)) { if (Z_TYPE_PP(data) == IS_ARRAY) { - if (key && zend_hash_find(Z_ARRVAL_PP(data), key, key_len + 1, (void**)&zvalue) == FAILURE) { + if (column && zend_hash_find(Z_ARRVAL_PP(data), column, column_len + 1, (void**)&zcolval) == FAILURE) { continue; - } else if (!key && zend_hash_index_find(Z_ARRVAL_PP(data), index, (void**)&zvalue) == FAILURE) { + } else if (!column && zend_hash_index_find(Z_ARRVAL_PP(data), column_idx, (void**)&zcolval) == FAILURE) { continue; } - Z_ADDREF_PP(zvalue); - add_next_index_zval(return_value, *zvalue); + Z_ADDREF_PP(zcolval); + + keyval = NULL; + keyval_idx = NULL; + + if (zkey) { + if (key && zend_hash_find(Z_ARRVAL_PP(data), key, key_len + 1, (void**)&zkeyval) == FAILURE) { + keyval_idx = NULL; + } else if (!key && zend_hash_index_find(Z_ARRVAL_PP(data), key_idx, (void**)&zkeyval) == FAILURE) { + keyval_idx = NULL; + } else { + switch (Z_TYPE_PP(zkeyval)) { + case IS_LONG: + keyval_idx = Z_LVAL_PP(zkeyval); + break; + case IS_STRING: + keyval = Z_STRVAL_PP(zkeyval); + break; + case IS_OBJECT: + convert_to_string(*zkeyval); + keyval = Z_STRVAL_PP(zkeyval); + break; + default: + keyval_idx = NULL; + } + } + } + + if (keyval) { + add_assoc_zval(return_value, keyval, *zcolval); + } else if (keyval_idx != NULL) { + add_index_zval(return_value, keyval_idx, *zcolval); + } else { + add_next_index_zval(return_value, *zcolval); + } } } |