Commit: 5bc2854b37778d7f402db8bb9be9fe33df64258e
Author: Ben Ramsey <ram...@php.net> Fri, 11 Jan 2013 16:57:11 -0600
Parents: 94d5b2519aa6790e603cec7a054900941ffe07a9
Branches: PHP-5.5 master
Link:
http://git.php.net/?p=php-src.git;a=commitdiff;h=5bc2854b37778d7f402db8bb9be9fe33df64258e
Log:
array_column: Implement ability to specify an index column
Changed paths:
M ext/standard/array.c
M ext/standard/basic_functions.c
M ext/standard/tests/array/array_column_basic.phpt
M ext/standard/tests/array/array_column_error.phpt
diff --git a/ext/standard/array.c b/ext/standard/array.c
index 91a8833..fa19737 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 2e44150..5e12352 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 fa8fe2f..70ce213 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 d409d3b..1aec1ac 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
--
PHP CVS Mailing List (http://www.php.net/)
To unsubscribe, visit: http://www.php.net/unsub.php