diff options
author | Ben Ramsey <ramsey@php.net> | 2013-01-11 16:57:11 -0600 |
---|---|---|
committer | Ben Ramsey <ramsey@php.net> | 2013-01-11 16:58:31 -0600 |
commit | 5bc2854b37778d7f402db8bb9be9fe33df64258e (patch) | |
tree | aae8fbec6dba2d32d1916eb28bb9c24bb337f1a1 | |
parent | 94d5b2519aa6790e603cec7a054900941ffe07a9 (diff) | |
download | php-git-5bc2854b37778d7f402db8bb9be9fe33df64258e.tar.gz |
array_column: Implement ability to specify an index column
-rw-r--r-- | ext/standard/array.c | 97 | ||||
-rw-r--r-- | ext/standard/basic_functions.c | 3 | ||||
-rw-r--r-- | ext/standard/tests/array/array_column_basic.phpt | 123 | ||||
-rw-r--r-- | ext/standard/tests/array/array_column_error.phpt | 56 |
4 files changed, 235 insertions, 44 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); + } } } diff --git a/ext/standard/basic_functions.c b/ext/standard/basic_functions.c index 2e44150871..5e123528c3 100644 --- a/ext/standard/basic_functions.c +++ b/ext/standard/basic_functions.c @@ -435,7 +435,8 @@ ZEND_END_ARG_INFO() ZEND_BEGIN_ARG_INFO_EX(arginfo_array_column, 0, 0, 2) ZEND_ARG_INFO(0, arg) /* ARRAY_INFO(0, arg, 0) */ - ZEND_ARG_INFO(0, key) + ZEND_ARG_INFO(0, column_key) + ZEND_ARG_INFO(0, index_key) ZEND_END_ARG_INFO() ZEND_BEGIN_ARG_INFO_EX(arginfo_array_reverse, 0, 0, 1) diff --git a/ext/standard/tests/array/array_column_basic.phpt b/ext/standard/tests/array/array_column_basic.phpt index fa8fe2fb5a..70ce2136b4 100644 --- a/ext/standard/tests/array/array_column_basic.phpt +++ b/ext/standard/tests/array/array_column_basic.phpt @@ -3,7 +3,7 @@ Test array_column() function: basic functionality --FILE-- <?php /* Prototype: - * array array_column(array $input, mixed $key); + * array array_column(array $input, mixed $column_key[, mixed $index_key]); * Description: * Returns an array containing all the values from * the specified "column" in a two-dimensional array. @@ -35,6 +35,12 @@ var_dump(array_column($records, 'first_name')); echo "-- id column from recordset --\n"; var_dump(array_column($records, 'id')); +echo "-- last_name column from recordset, keyed by value from id column --\n"; +var_dump(array_column($records, 'last_name', 'id')); + +echo "-- last_name column from recordset, keyed by value from first_name column --\n"; +var_dump(array_column($records, 'last_name', 'first_name')); + echo "\n*** Testing multiple data types ***\n"; $file = basename(__FILE__); $fh = fopen($file, 'r', true); @@ -73,6 +79,7 @@ $values = array( ) ); var_dump(array_column($values, 'value')); +var_dump(array_column($values, 'value', 'id')); echo "\n*** Testing numeric column keys ***\n"; $numericCols = array( @@ -81,10 +88,12 @@ $numericCols = array( array('ccc', '333') ); var_dump(array_column($numericCols, 1)); +var_dump(array_column($numericCols, 1, 0)); echo "\n*** Testing failure to find specified column ***\n"; var_dump(array_column($numericCols, 2)); var_dump(array_column($numericCols, 'foo')); +var_dump(array_column($numericCols, 0, 'foo')); echo "\n*** Testing single dimensional array ***\n"; $singleDimension = array('foo', 'bar', 'baz'); @@ -92,10 +101,16 @@ var_dump(array_column($singleDimension, 1)); echo "\n*** Testing columns not present in all rows ***\n"; $mismatchedColumns = array( - array('a' => 'foo', 'b' => 'bar'), - array('a' => 'baz', 'c' => 'qux'), + array('a' => 'foo', 'b' => 'bar', 'e' => 'bbb'), + array('a' => 'baz', 'c' => 'qux', 'd' => 'aaa'), + array('a' => 'eee', 'b' => 'fff', 'e' => 'ggg'), ); var_dump(array_column($mismatchedColumns, 'c')); +var_dump(array_column($mismatchedColumns, 'c', 'a')); +var_dump(array_column($mismatchedColumns, 'a', 'd')); +var_dump(array_column($mismatchedColumns, 'a', 'e')); +var_dump(array_column($mismatchedColumns, 'b')); +var_dump(array_column($mismatchedColumns, 'b', 'a')); echo "\n*** Testing use of object converted to string ***\n"; class Foo @@ -105,8 +120,17 @@ class Foo return 'last_name'; } } +class Bar +{ + public function __toString() + { + return 'first_name'; + } +} $f = new Foo(); +$b = new Bar(); var_dump(array_column($records, $f)); +var_dump(array_column($records, $f, $b)); echo "Done\n"; ?> @@ -130,6 +154,24 @@ array(3) { [2]=> int(3) } +-- last_name column from recordset, keyed by value from id column -- +array(3) { + [1]=> + string(3) "Doe" + [2]=> + string(5) "Smith" + [3]=> + string(5) "Jones" +} +-- last_name column from recordset, keyed by value from first_name column -- +array(3) { + ["John"]=> + string(3) "Doe" + ["Sally"]=> + string(5) "Smith" + ["Jane"]=> + string(5) "Jones" +} *** Testing multiple data types *** array(8) { @@ -151,6 +193,25 @@ array(8) { [7]=> resource(5) of type (stream) } +array(8) { + [1]=> + object(stdClass)#1 (0) { + } + [2]=> + float(34.2345) + [3]=> + bool(true) + [4]=> + bool(false) + [5]=> + NULL + [6]=> + int(1234) + [7]=> + string(3) "Foo" + [8]=> + resource(5) of type (stream) +} *** Testing numeric column keys *** array(3) { @@ -161,12 +222,28 @@ array(3) { [2]=> string(3) "333" } +array(3) { + ["aaa"]=> + string(3) "111" + ["bbb"]=> + string(3) "222" + ["ccc"]=> + string(3) "333" +} *** Testing failure to find specified column *** array(0) { } array(0) { } +array(3) { + [0]=> + string(3) "aaa" + [1]=> + string(3) "bbb" + [2]=> + string(3) "ccc" +} *** Testing single dimensional array *** array(0) { @@ -177,6 +254,38 @@ array(1) { [0]=> string(3) "qux" } +array(1) { + ["baz"]=> + string(3) "qux" +} +array(3) { + [0]=> + string(3) "foo" + ["aaa"]=> + string(3) "baz" + [1]=> + string(3) "eee" +} +array(3) { + ["bbb"]=> + string(3) "foo" + [0]=> + string(3) "baz" + ["ggg"]=> + string(3) "eee" +} +array(2) { + [0]=> + string(3) "bar" + [1]=> + string(3) "fff" +} +array(2) { + ["foo"]=> + string(3) "bar" + ["eee"]=> + string(3) "fff" +} *** Testing use of object converted to string *** array(3) { @@ -187,4 +296,12 @@ array(3) { [2]=> string(5) "Jones" } +array(3) { + ["John"]=> + string(3) "Doe" + ["Sally"]=> + string(5) "Smith" + ["Jane"]=> + string(5) "Jones" +} Done diff --git a/ext/standard/tests/array/array_column_error.phpt b/ext/standard/tests/array/array_column_error.phpt index d409d3b12e..1aec1acc63 100644 --- a/ext/standard/tests/array/array_column_error.phpt +++ b/ext/standard/tests/array/array_column_error.phpt @@ -3,7 +3,7 @@ Test array_column() function: error conditions --FILE-- <?php /* Prototype: - * array array_column(array $input, mixed $key); + * array array_column(array $input, mixed $column_key[, mixed $index_key]); * Description: * Returns an array containing all the values from * the specified "column" in a two-dimensional array. @@ -17,24 +17,30 @@ var_dump(array_column()); echo "\n-- Testing array_column() function with One argument --\n"; var_dump(array_column(array())); -echo "\n-- Testing array_column() function with more than expected no. of arguments --\n"; -var_dump(array_column(array(), 'foo', 'bar')); - echo "\n-- Testing array_column() function with string as first parameter --\n"; var_dump(array_column('foo', 0)); echo "\n-- Testing array_column() function with int as first parameter --\n"; var_dump(array_column(1, 'foo')); -echo "\n-- Testing array_column() key parameter should be a string or an integer (testing bool) --\n"; +echo "\n-- Testing array_column() column key parameter should be a string or an integer (testing bool) --\n"; var_dump(array_column(array(), true)); -echo "\n-- Testing array_column() key parameter should be a string or integer (testing float) --\n"; +echo "\n-- Testing array_column() column key parameter should be a string or integer (testing float) --\n"; var_dump(array_column(array(), 2.3)); -echo "\n-- Testing array_column() key parameter should be a string or integer (testing array) --\n"; +echo "\n-- Testing array_column() column key parameter should be a string or integer (testing array) --\n"; var_dump(array_column(array(), array())); +echo "\n-- Testing array_column() index key parameter should be a string or an integer (testing bool) --\n"; +var_dump(array_column(array(), 'foo', true)); + +echo "\n-- Testing array_column() index key parameter should be a string or integer (testing float) --\n"; +var_dump(array_column(array(), 'foo', 2.3)); + +echo "\n-- Testing array_column() index key parameter should be a string or integer (testing array) --\n"; +var_dump(array_column(array(), 'foo', array())); + echo "Done\n"; ?> --EXPECTF-- @@ -42,17 +48,12 @@ echo "Done\n"; -- Testing array_column() function with Zero arguments -- -Warning: array_column() expects exactly 2 parameters, 0 given in %s on line %d +Warning: array_column() expects at least 2 parameters, 0 given in %s on line %d NULL -- Testing array_column() function with One argument -- -Warning: array_column() expects exactly 2 parameters, 1 given in %s on line %d -NULL - --- Testing array_column() function with more than expected no. of arguments -- - -Warning: array_column() expects exactly 2 parameters, 3 given in %s on line %d +Warning: array_column() expects at least 2 parameters, 1 given in %s on line %d NULL -- Testing array_column() function with string as first parameter -- @@ -65,18 +66,33 @@ NULL Warning: array_column() expects parameter 1 to be array, integer given in %s on line %d NULL --- Testing array_column() key parameter should be a string or an integer (testing bool) -- +-- Testing array_column() column key parameter should be a string or an integer (testing bool) -- + +Warning: array_column(): The column key should be either a string or an integer in %s on line %d +bool(false) + +-- Testing array_column() column key parameter should be a string or integer (testing float) -- + +Warning: array_column(): The column key should be either a string or an integer in %s on line %d +bool(false) + +-- Testing array_column() column key parameter should be a string or integer (testing array) -- + +Warning: array_column(): The column key should be either a string or an integer in %s on line %d +bool(false) + +-- Testing array_column() index key parameter should be a string or an integer (testing bool) -- -Warning: array_column(): The key should be either a string or an integer in %s on line %d +Warning: array_column(): The index key should be either a string or an integer in %s on line %d bool(false) --- Testing array_column() key parameter should be a string or integer (testing float) -- +-- Testing array_column() index key parameter should be a string or integer (testing float) -- -Warning: array_column(): The key should be either a string or an integer in %s on line %d +Warning: array_column(): The index key should be either a string or an integer in %s on line %d bool(false) --- Testing array_column() key parameter should be a string or integer (testing array) -- +-- Testing array_column() index key parameter should be a string or integer (testing array) -- -Warning: array_column(): The key should be either a string or an integer in %s on line %d +Warning: array_column(): The index key should be either a string or an integer in %s on line %d bool(false) Done |