Skip to content

Commit 091d53c

Browse files
committed
Use standard key behavior in array_column()
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.
1 parent b111674 commit 091d53c

File tree

3 files changed

+23
-51
lines changed

3 files changed

+23
-51
lines changed

ext/standard/array.c

Lines changed: 2 additions & 39 deletions
Original file line numberDiff line numberDiff line change
@@ -4174,48 +4174,11 @@ PHP_FUNCTION(array_column)
41744174
continue;
41754175
}
41764176

4177-
/* Failure will leave keyval alone which will land us on the final else block below
4178-
* which is to append the value as next_index
4179-
*/
41804177
zval rv;
41814178
zval *keyval = array_column_fetch_prop(data, index_str, index_long, &rv);
4182-
41834179
if (keyval) {
4184-
switch (Z_TYPE_P(keyval)) {
4185-
case IS_STRING:
4186-
zend_symtable_update(Z_ARRVAL_P(return_value), Z_STR_P(keyval), colval);
4187-
break;
4188-
case IS_LONG:
4189-
zend_hash_index_update(Z_ARRVAL_P(return_value), Z_LVAL_P(keyval), colval);
4190-
break;
4191-
case IS_OBJECT:
4192-
{
4193-
zend_string *tmp_key;
4194-
zend_string *key = zval_get_tmp_string(keyval, &tmp_key);
4195-
zend_symtable_update(Z_ARRVAL_P(return_value), key, colval);
4196-
zend_tmp_string_release(tmp_key);
4197-
break;
4198-
}
4199-
case IS_NULL:
4200-
zend_hash_update(Z_ARRVAL_P(return_value), ZSTR_EMPTY_ALLOC(), colval);
4201-
break;
4202-
case IS_DOUBLE:
4203-
zend_hash_index_update(Z_ARRVAL_P(return_value),
4204-
zend_dval_to_lval(Z_DVAL_P(keyval)), colval);
4205-
break;
4206-
case IS_TRUE:
4207-
zend_hash_index_update(Z_ARRVAL_P(return_value), 1, colval);
4208-
break;
4209-
case IS_FALSE:
4210-
zend_hash_index_update(Z_ARRVAL_P(return_value), 0, colval);
4211-
break;
4212-
case IS_RESOURCE:
4213-
zend_hash_index_update(Z_ARRVAL_P(return_value), Z_RES_HANDLE_P(keyval), colval);
4214-
break;
4215-
default:
4216-
zend_hash_next_index_insert(Z_ARRVAL_P(return_value), colval);
4217-
break;
4218-
}
4180+
array_set_zval_key(Z_ARRVAL_P(return_value), keyval, colval);
4181+
zval_ptr_dtor(colval);
42194182
zval_ptr_dtor(keyval);
42204183
} else {
42214184
zend_hash_next_index_insert(Z_ARRVAL_P(return_value), colval);

ext/standard/tests/array/array_column_object_cast.phpt

Lines changed: 6 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -10,20 +10,15 @@ class IndexKeyClass {
1010
function __toString() { return 'id'; }
1111
}
1212

13-
class ValueClass {
14-
function __toString() { return '2135'; }
15-
}
16-
1713

1814
$column_key = new ColumnKeyClass();
1915
$index_key = new IndexKeyClass();
20-
$value = new ValueClass();
2116

2217

2318
// Array representing a possible record set returned from a database
2419
$records = array(
2520
array(
26-
'id' => $value,
21+
'id' => 2135,
2722
'first_name' => 'John',
2823
'last_name' => 'XXX'
2924
),
@@ -37,16 +32,15 @@ $firstNames = array_column($records, $column_key, $index_key);
3732
print_r($firstNames);
3833
var_dump($column_key);
3934
var_dump($index_key);
40-
var_dump($value);
41-
--EXPECTF--
35+
36+
?>
37+
--EXPECT--
4238
Array
4339
(
4440
[2135] => John
4541
[3245] => Sally
4642
)
47-
object(ColumnKeyClass)#%d (0) {
48-
}
49-
object(IndexKeyClass)#%d (0) {
43+
object(ColumnKeyClass)#1 (0) {
5044
}
51-
object(ValueClass)#%d (0) {
45+
object(IndexKeyClass)#2 (0) {
5246
}

ext/standard/tests/array/bug68553.phpt

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -21,7 +21,20 @@ $a = [
2121
];
2222

2323
var_dump(array_column($a, null, 'a'));
24+
25+
try {
26+
var_dump(array_column([['a' => new stdClass]], null, 'a'));
27+
} catch (Error $e) {
28+
echo $e->getMessage(), "\n";
29+
}
30+
try {
31+
var_dump(array_column([['a' => []]], null, 'a'));
32+
} catch (Error $e) {
33+
echo $e->getMessage(), "\n";
34+
}
35+
?>
2436
--EXPECTF--
37+
Warning: Resource ID#%d used as offset, casting to integer (%d) in %s on line %d
2538
array(8) {
2639
[10]=>
2740
array(1) {
@@ -64,3 +77,5 @@ array(8) {
6477
NULL
6578
}
6679
}
80+
Illegal offset type
81+
Illegal offset type

0 commit comments

Comments
 (0)