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

Reply via email to