]> granicus.if.org Git - php/commitdiff
Use standard key behavior in array_column()
authorNikita Popov <nikita.ppv@gmail.com>
Wed, 29 Apr 2020 08:35:44 +0000 (10:35 +0200)
committerNikita Popov <nikita.ppv@gmail.com>
Mon, 11 May 2020 12:16:24 +0000 (14:16 +0200)
array_column() reimplements array key handling in a way that does
not match standard array key behavior in PHP. Avoid this by making
use of the standard API.

Of course, there is a minor backwards compatibilty break here,
e.g. people could be relying on objects getting cast to string
instead of throwing.

Closes GH-5487.

ext/standard/array.c
ext/standard/tests/array/array_column_object_cast.phpt
ext/standard/tests/array/bug68553.phpt

index 3e54946cd040ca4920cab10fa1318d705dc4eac6..fd0ceaa6006cf19fc618879fb9ca58f5418e5501 100644 (file)
@@ -4174,48 +4174,11 @@ PHP_FUNCTION(array_column)
                                continue;
                        }
 
-                       /* Failure will leave keyval alone which will land us on the final else block below
-                        * which is to append the value as next_index
-                        */
                        zval rv;
                        zval *keyval = array_column_fetch_prop(data, index_str, index_long, &rv);
-
                        if (keyval) {
-                               switch (Z_TYPE_P(keyval)) {
-                                       case IS_STRING:
-                                               zend_symtable_update(Z_ARRVAL_P(return_value), Z_STR_P(keyval), colval);
-                                               break;
-                                       case IS_LONG:
-                                               zend_hash_index_update(Z_ARRVAL_P(return_value), Z_LVAL_P(keyval), colval);
-                                               break;
-                                       case IS_OBJECT:
-                                               {
-                                                       zend_string *tmp_key;
-                                                       zend_string *key = zval_get_tmp_string(keyval, &tmp_key);
-                                                       zend_symtable_update(Z_ARRVAL_P(return_value), key, colval);
-                                                       zend_tmp_string_release(tmp_key);
-                                                       break;
-                                               }
-                                       case IS_NULL:
-                                               zend_hash_update(Z_ARRVAL_P(return_value), ZSTR_EMPTY_ALLOC(), colval);
-                                               break;
-                                       case IS_DOUBLE:
-                                               zend_hash_index_update(Z_ARRVAL_P(return_value),
-                                                               zend_dval_to_lval(Z_DVAL_P(keyval)), colval);
-                                               break;
-                                       case IS_TRUE:
-                                               zend_hash_index_update(Z_ARRVAL_P(return_value), 1, colval);
-                                               break;
-                                       case IS_FALSE:
-                                               zend_hash_index_update(Z_ARRVAL_P(return_value), 0, colval);
-                                               break;
-                                       case IS_RESOURCE:
-                                               zend_hash_index_update(Z_ARRVAL_P(return_value), Z_RES_HANDLE_P(keyval), colval);
-                                               break;
-                                       default:
-                                               zend_hash_next_index_insert(Z_ARRVAL_P(return_value), colval);
-                                               break;
-                               }
+                               array_set_zval_key(Z_ARRVAL_P(return_value), keyval, colval);
+                               zval_ptr_dtor(colval);
                                zval_ptr_dtor(keyval);
                        } else {
                                zend_hash_next_index_insert(Z_ARRVAL_P(return_value), colval);
index 762aaa81f4b9568ebfe82e732454d0d6021c5005..5e80b1da59aa9d63927b156bc419bfe400aeb3e4 100644 (file)
@@ -10,20 +10,15 @@ class IndexKeyClass {
     function __toString() { return 'id'; }
 }
 
-class ValueClass {
-    function __toString() { return '2135'; }
-}
-
 
 $column_key = new ColumnKeyClass();
 $index_key = new IndexKeyClass();
-$value = new ValueClass();
 
 
 // Array representing a possible record set returned from a database
 $records = array(
     array(
-        'id' => $value,
+        'id' => 2135,
         'first_name' => 'John',
         'last_name' => 'XXX'
     ),
@@ -37,16 +32,15 @@ $firstNames = array_column($records, $column_key, $index_key);
 print_r($firstNames);
 var_dump($column_key);
 var_dump($index_key);
-var_dump($value);
---EXPECTF--
+
+?>
+--EXPECT--
 Array
 (
     [2135] => John
     [3245] => Sally
 )
-object(ColumnKeyClass)#%d (0) {
-}
-object(IndexKeyClass)#%d (0) {
+object(ColumnKeyClass)#1 (0) {
 }
-object(ValueClass)#%d (0) {
+object(IndexKeyClass)#2 (0) {
 }
index 966c98b544a78a6bbd3f465256dbeb79a4e847a7..1d8f7f1b0b4e531b619667975e1e19446644b47d 100644 (file)
@@ -21,7 +21,20 @@ $a = [
 ];
 
 var_dump(array_column($a, null, 'a'));
+
+try {
+    var_dump(array_column([['a' => new stdClass]], null, 'a'));
+} catch (Error $e) {
+    echo $e->getMessage(), "\n";
+}
+try {
+    var_dump(array_column([['a' => []]], null, 'a'));
+} catch (Error $e) {
+    echo $e->getMessage(), "\n";
+}
+?>
 --EXPECTF--
+Warning: Resource ID#%d used as offset, casting to integer (%d) in %s on line %d
 array(8) {
   [10]=>
   array(1) {
@@ -64,3 +77,5 @@ array(8) {
     NULL
   }
 }
+Illegal offset type
+Illegal offset type