Skip to content

Commit d2e9a29

Browse files
Add array_get and array_has functions
# Conflicts: # ext/standard/basic_functions_arginfo.h # ext/standard/basic_functions_decl.h # Conflicts: # ext/standard/basic_functions_arginfo.h # ext/standard/basic_functions_decl.h
1 parent 9498bc3 commit d2e9a29

4 files changed

Lines changed: 138 additions & 5 deletions

File tree

ext/standard/array.c

Lines changed: 108 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -6913,6 +6913,114 @@ PHP_FUNCTION(array_key_exists)
69136913
}
69146914
/* }}} */
69156915

6916+
/* {{{ Helper function to get a nested value from array using dot notation */
6917+
static zval* array_get_nested(HashTable *ht, const char *key, size_t key_len)
6918+
{
6919+
const char *dot;
6920+
zval *current;
6921+
6922+
/* Find the first dot in the key */
6923+
dot = memchr(key, '.', key_len);
6924+
6925+
if (dot == NULL) {
6926+
/* No dot found, this is a simple key lookup */
6927+
zend_string *zkey = zend_string_init(key, key_len, 0);
6928+
current = zend_symtable_find(ht, zkey);
6929+
zend_string_release(zkey);
6930+
return current;
6931+
}
6932+
6933+
/* We have a dot, so we need to recurse */
6934+
size_t segment_len = dot - key;
6935+
zend_string *segment = zend_string_init(key, segment_len, 0);
6936+
current = zend_symtable_find(ht, segment);
6937+
zend_string_release(segment);
6938+
6939+
if (current == NULL || Z_TYPE_P(current) != IS_ARRAY) {
6940+
return NULL;
6941+
}
6942+
6943+
/* Recurse into the nested array with the remaining key */
6944+
return array_get_nested(Z_ARRVAL_P(current), dot + 1, key_len - segment_len - 1);
6945+
}
6946+
/* }}} */
6947+
6948+
/* {{{ Retrieves a value from a deeply nested array using "dot" notation */
6949+
PHP_FUNCTION(array_get)
6950+
{
6951+
HashTable *ht;
6952+
zval *key = NULL;
6953+
zval *default_value = NULL;
6954+
zval *result;
6955+
6956+
ZEND_PARSE_PARAMETERS_START(2, 3)
6957+
Z_PARAM_ARRAY_HT(ht)
6958+
Z_PARAM_ZVAL_OR_NULL(key)
6959+
Z_PARAM_OPTIONAL
6960+
Z_PARAM_ZVAL(default_value)
6961+
ZEND_PARSE_PARAMETERS_END();
6962+
6963+
/* If key is null, return the whole array */
6964+
if (key == NULL || Z_TYPE_P(key) == IS_NULL) {
6965+
ZVAL_ARR(return_value, zend_array_dup(ht));
6966+
return;
6967+
}
6968+
6969+
/* Handle string keys with dot notation */
6970+
if (Z_TYPE_P(key) == IS_STRING) {
6971+
result = array_get_nested(ht, Z_STRVAL_P(key), Z_STRLEN_P(key));
6972+
6973+
if (result != NULL) {
6974+
ZVAL_COPY(return_value, result);
6975+
return;
6976+
}
6977+
}
6978+
/* Handle integer keys (no dot notation support) */
6979+
else if (Z_TYPE_P(key) == IS_LONG) {
6980+
result = zend_hash_index_find(ht, Z_LVAL_P(key));
6981+
6982+
if (result != NULL) {
6983+
ZVAL_COPY(return_value, result);
6984+
return;
6985+
}
6986+
}
6987+
6988+
/* Key not found, return default value */
6989+
if (default_value != NULL) {
6990+
ZVAL_COPY(return_value, default_value);
6991+
} else {
6992+
RETVAL_NULL();
6993+
}
6994+
}
6995+
/* }}} */
6996+
6997+
/* {{{ Checks whether a given item exists in an array using "dot" notation */
6998+
PHP_FUNCTION(array_has)
6999+
{
7000+
HashTable *ht;
7001+
zval *key;
7002+
zval *result;
7003+
7004+
ZEND_PARSE_PARAMETERS_START(2, 2)
7005+
Z_PARAM_ARRAY_HT(ht)
7006+
Z_PARAM_ZVAL(key)
7007+
ZEND_PARSE_PARAMETERS_END();
7008+
7009+
/* Handle string keys with dot notation */
7010+
if (Z_TYPE_P(key) == IS_STRING) {
7011+
result = array_get_nested(ht, Z_STRVAL_P(key), Z_STRLEN_P(key));
7012+
RETURN_BOOL(result != NULL);
7013+
}
7014+
/* Handle integer keys (no dot notation support) */
7015+
else if (Z_TYPE_P(key) == IS_LONG) {
7016+
RETURN_BOOL(zend_hash_index_exists(ht, Z_LVAL_P(key)));
7017+
}
7018+
7019+
/* Invalid key type */
7020+
RETURN_FALSE;
7021+
}
7022+
/* }}} */
7023+
69167024
/* {{{ Split array into chunks */
69177025
PHP_FUNCTION(array_chunk)
69187026
{

ext/standard/basic_functions.stub.php

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1907,6 +1907,16 @@ function array_key_exists($key, array $array): bool {}
19071907
*/
19081908
function key_exists($key, array $array): bool {}
19091909

1910+
/**
1911+
* @compile-time-eval
1912+
*/
1913+
function array_get(array $array, string|int|null $key = null, mixed $default = null): mixed {}
1914+
1915+
/**
1916+
* @compile-time-eval
1917+
*/
1918+
function array_has(array $array, string|int $key): bool {}
1919+
19101920
/**
19111921
* @compile-time-eval
19121922
*/

ext/standard/basic_functions_arginfo.h

Lines changed: 16 additions & 1 deletion
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

ext/standard/basic_functions_decl.h

Lines changed: 4 additions & 4 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

0 commit comments

Comments
 (0)