}
/* }}} */
-/* {{{ array_column_param_helper
- * Specialized conversion rules for array_column() function
- */
-static inline
-zend_bool array_column_param_helper(zval *param, int parameter_number) {
- switch (Z_TYPE_P(param)) {
- case IS_DOUBLE:
- convert_to_long_ex(param);
- /* fallthrough */
- case IS_LONG:
- return 1;
-
- case IS_OBJECT:
- if (!try_convert_to_string(param)) {
- return 0;
- }
- /* fallthrough */
- case IS_STRING:
- return 1;
-
- default:
- zend_argument_type_error(parameter_number, "must be of type string|int, %s given", zend_zval_type_name(param));
- return 0;
- }
-}
-/* }}} */
-
-static inline zval *array_column_fetch_prop(zval *data, zval *name, zval *rv) /* {{{ */
+static inline zval *array_column_fetch_prop(zval *data, zend_string *name_str, zend_long name_long, zval *rv) /* {{{ */
{
zval *prop = NULL;
if (Z_TYPE_P(data) == IS_OBJECT) {
+ zend_string *tmp_str;
+ /* If name is an integer convert integer to string */
+ if (name_str == NULL) {
+ tmp_str = zend_long_to_str(name_long);
+ } else {
+ tmp_str = zend_string_copy(name_str);
+ }
/* The has_property check is first performed in "exists" mode (which returns true for
* properties that are null but exist) and then in "has" mode to handle objects that
* implement __isset (which is not called in "exists" mode). */
- zend_string *str, *tmp_str;
-
- str = zval_get_tmp_string(name, &tmp_str);
- if (Z_OBJ_HANDLER_P(data, has_property)(Z_OBJ_P(data), str, ZEND_PROPERTY_EXISTS, NULL)
- || Z_OBJ_HANDLER_P(data, has_property)(Z_OBJ_P(data), str, ZEND_PROPERTY_ISSET, NULL)) {
- prop = Z_OBJ_HANDLER_P(data, read_property)(Z_OBJ_P(data), str, BP_VAR_R, NULL, rv);
+ if (Z_OBJ_HANDLER_P(data, has_property)(Z_OBJ_P(data), tmp_str, ZEND_PROPERTY_EXISTS, NULL)
+ || Z_OBJ_HANDLER_P(data, has_property)(Z_OBJ_P(data), tmp_str, ZEND_PROPERTY_ISSET, NULL)) {
+ prop = Z_OBJ_HANDLER_P(data, read_property)(Z_OBJ_P(data), tmp_str, BP_VAR_R, NULL, rv);
if (prop) {
ZVAL_DEREF(prop);
if (prop != rv) {
}
}
}
- zend_tmp_string_release(tmp_str);
+ zend_string_release(tmp_str);
} else if (Z_TYPE_P(data) == IS_ARRAY) {
- if (Z_TYPE_P(name) == IS_STRING) {
- prop = zend_symtable_find(Z_ARRVAL_P(data), Z_STR_P(name));
- } else if (Z_TYPE_P(name) == IS_LONG) {
- prop = zend_hash_index_find(Z_ARRVAL_P(data), Z_LVAL_P(name));
+ /* Name is a string */
+ if (name_str != NULL) {
+ prop = zend_symtable_find(Z_ARRVAL_P(data), name_str);
+ } else {
+ prop = zend_hash_index_find(Z_ARRVAL_P(data), name_long);
}
if (prop) {
ZVAL_DEREF(prop);
}
}
-
return prop;
}
/* }}} */
-/* {{{ proto array array_column(array input, mixed column_key[, mixed index_key])
+/* {{{ proto array array_column(array input, string|int|null column_key[, string|int|null 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)
{
HashTable *input;
zval *colval, *data, rv;
- zval *column = NULL, *index = NULL;
+ zend_string *column_str = NULL;
+ zend_long column_long;
+ zend_bool column_is_null = 0;
+ zend_string *index_str = NULL;
+ zend_long index_long;
+ zend_bool index_is_null = 1;
ZEND_PARSE_PARAMETERS_START(2, 3)
Z_PARAM_ARRAY_HT(input)
- Z_PARAM_ZVAL_EX(column, 1, 0)
+ Z_PARAM_STR_OR_LONG_OR_NULL(column_str, column_long, column_is_null)
Z_PARAM_OPTIONAL
- Z_PARAM_ZVAL_EX(index, 1, 0)
+ Z_PARAM_STR_OR_LONG_OR_NULL(index_str, index_long, index_is_null)
ZEND_PARSE_PARAMETERS_END();
- if ((column && !array_column_param_helper(column, 2)) ||
- (index && !array_column_param_helper(index, 3))) {
- RETURN_THROWS();
- }
-
array_init_size(return_value, zend_hash_num_elements(input));
- if (!index) {
+ /* Index param is not passed */
+ if (index_is_null) {
zend_hash_real_init_packed(Z_ARRVAL_P(return_value));
ZEND_HASH_FILL_PACKED(Z_ARRVAL_P(return_value)) {
ZEND_HASH_FOREACH_VAL(input, data) {
ZVAL_DEREF(data);
- if (!column) {
+ if (column_is_null) {
Z_TRY_ADDREF_P(data);
colval = data;
- } else if ((colval = array_column_fetch_prop(data, column, &rv)) == NULL) {
+ } else if ((colval = array_column_fetch_prop(data, column_str, column_long, &rv)) == NULL) {
continue;
}
ZEND_HASH_FILL_ADD(colval);
ZEND_HASH_FOREACH_VAL(input, data) {
ZVAL_DEREF(data);
- if (!column) {
+ if (column_is_null) {
Z_TRY_ADDREF_P(data);
colval = data;
- } else if ((colval = array_column_fetch_prop(data, column, &rv)) == NULL) {
+ } else if ((colval = array_column_fetch_prop(data, column_str, column_long, &rv)) == NULL) {
continue;
}
* which is to append the value as next_index
*/
zval rv;
- zval *keyval = array_column_fetch_prop(data, index, &rv);
+ zval *keyval = array_column_fetch_prop(data, index_str, index_long, &rv);
if (keyval) {
switch (Z_TYPE_P(keyval)) {
function array_count_values(array $arg): array {}
-/**
- * @param int|string|null $column_key
- * @param int|string|null $index_key
- */
-function array_column(array $arg, $column_key, $index_key = null): array {}
+function array_column(array $arg, int|string|null $column_key, int|string|null $index_key = null): array {}
function array_reverse(array $input, bool $preserve_keys = false): array {}
ZEND_BEGIN_ARG_WITH_RETURN_TYPE_INFO_EX(arginfo_array_column, 0, 2, IS_ARRAY, 0)
ZEND_ARG_TYPE_INFO(0, arg, IS_ARRAY, 0)
- ZEND_ARG_INFO(0, column_key)
- ZEND_ARG_INFO_WITH_DEFAULT_VALUE(0, index_key, "null")
+ ZEND_ARG_TYPE_MASK(0, column_key, MAY_BE_LONG|MAY_BE_STRING|MAY_BE_NULL, NULL)
+ ZEND_ARG_TYPE_MASK(0, index_key, MAY_BE_LONG|MAY_BE_STRING|MAY_BE_NULL, "null")
ZEND_END_ARG_INFO()
ZEND_BEGIN_ARG_WITH_RETURN_TYPE_INFO_EX(arginfo_array_reverse, 0, 1, IS_ARRAY, 0)
--TEST--
-Test array_column() function: error conditions
+Test array_column(): Index argument with various types in strict type mode
--FILE--
<?php
+declare(strict_types=1);
/* Prototype:
* array array_column(array $input, mixed $column_key[, mixed $index_key]);
* Description:
* the specified "column" in a two-dimensional array.
*/
-echo "*** Testing array_column() : error conditions ***\n";
echo "\n-- Testing array_column() column key parameter should be a string or an integer (testing bool) --\n";
try {
- var_dump(array_column(array(), true));
+ var_dump(array_column([['php7', 'foo'], ['php8', 'bar']], false));
+} catch (\TypeError $e) {
+ echo $e->getMessage() . "\n";
+}
+try {
+ var_dump(array_column([['php7', 'foo'], ['php8', 'bar']], true));
} catch (\TypeError $e) {
echo $e->getMessage() . "\n";
}
-
echo "\n-- Testing array_column() column key parameter should be a string or integer (testing array) --\n";
try {
- var_dump(array_column(array(), array()));
+ var_dump(array_column([['php7', 'foo'], ['php8', 'bar']], array()));
} catch (\TypeError $e) {
echo $e->getMessage() . "\n";
}
echo "\n-- Testing array_column() index key parameter should be a string or an integer (testing bool) --\n";
try {
- var_dump(array_column(array(), 'foo', true));
+ var_dump(array_column([['php' => 7, 'foo'], ['php' => 8, 'bar']], 'php', false));
+} catch (\TypeError $e) {
+ echo $e->getMessage() . "\n";
+}
+try {
+ var_dump(array_column([['php' => 7, 'foo'], ['php' => 8, 'bar']], 'php', true));
} catch (\TypeError $e) {
echo $e->getMessage() . "\n";
}
echo "\n-- Testing array_column() index key parameter should be a string or integer (testing array) --\n";
try {
- var_dump(array_column(array(), 'foo', array()));
+ var_dump(array_column([['php' => 7, 'foo'], ['php' => 8, 'bar']], 'php', array()));
} catch (\TypeError $e) {
echo $e->getMessage() . "\n";
}
DONE
--EXPECT--
-*** Testing array_column() : error conditions ***
-
-- Testing array_column() column key parameter should be a string or an integer (testing bool) --
-array_column(): Argument #2 ($column_key) must be of type string|int, bool given
+array_column(): Argument #2 ($column_key) must be of type string|int|null, bool given
+array_column(): Argument #2 ($column_key) must be of type string|int|null, bool given
-- Testing array_column() column key parameter should be a string or integer (testing array) --
-array_column(): Argument #2 ($column_key) must be of type string|int, array given
+array_column(): Argument #2 ($column_key) must be of type string|int|null, array given
-- Testing array_column() index key parameter should be a string or an integer (testing bool) --
-array_column(): Argument #3 ($index_key) must be of type string|int, bool given
+array_column(): Argument #3 ($index_key) must be of type string|int|null, bool given
+array_column(): Argument #3 ($index_key) must be of type string|int|null, bool given
-- Testing array_column() index key parameter should be a string or integer (testing array) --
-array_column(): Argument #3 ($index_key) must be of type string|int, array given
+array_column(): Argument #3 ($index_key) must be of type string|int|null, array given
DONE
--- /dev/null
+--TEST--
+Test array_column(): Index argument with various types in weak type mode
+--FILE--
+<?php
+/* Prototype:
+ * 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.
+ */
+
+echo "\n-- Testing array_column() column key parameter should be a string or an integer (testing bool) --\n";
+try {
+ var_dump(array_column([['php7', 'foo'], ['php8', 'bar']], false));
+} catch (\TypeError $e) {
+ echo $e->getMessage() . "\n";
+}
+try {
+ var_dump(array_column([['php7', 'foo'], ['php8', 'bar']], true));
+} catch (\TypeError $e) {
+ echo $e->getMessage() . "\n";
+}
+
+echo "\n-- Testing array_column() column key parameter should be a string or integer (testing array) --\n";
+try {
+ var_dump(array_column([['php7', 'foo'], ['php8', 'bar']], array()));
+} catch (\TypeError $e) {
+ echo $e->getMessage() . "\n";
+}
+
+echo "\n-- Testing array_column() index key parameter should be a string or an integer (testing bool) --\n";
+try {
+ var_dump(array_column([['php' => 7, 'foo'], ['php' => 8, 'bar']], 'php', false));
+} catch (\TypeError $e) {
+ echo $e->getMessage() . "\n";
+}
+try {
+ var_dump(array_column([['php' => 7, 'foo'], ['php' => 8, 'bar']], 'php', true));
+} catch (\TypeError $e) {
+ echo $e->getMessage() . "\n";
+}
+
+echo "\n-- Testing array_column() index key parameter should be a string or integer (testing array) --\n";
+try {
+ var_dump(array_column([['php' => 7, 'foo'], ['php' => 8, 'bar']], 'php', array()));
+} catch (\TypeError $e) {
+ echo $e->getMessage() . "\n";
+}
+
+?>
+
+DONE
+--EXPECT--
+-- Testing array_column() column key parameter should be a string or an integer (testing bool) --
+array(2) {
+ [0]=>
+ string(4) "php7"
+ [1]=>
+ string(4) "php8"
+}
+array(2) {
+ [0]=>
+ string(3) "foo"
+ [1]=>
+ string(3) "bar"
+}
+
+-- Testing array_column() column key parameter should be a string or integer (testing array) --
+array_column(): Argument #2 ($column_key) must be of type string|int|null, array given
+
+-- Testing array_column() index key parameter should be a string or an integer (testing bool) --
+array(2) {
+ ["foo"]=>
+ int(7)
+ ["bar"]=>
+ int(8)
+}
+array(2) {
+ [0]=>
+ int(7)
+ [1]=>
+ int(8)
+}
+
+-- Testing array_column() index key parameter should be a string or integer (testing array) --
+array_column(): Argument #3 ($index_key) must be of type string|int|null, array given
+
+DONE