Skip to content

Commit 952d028

Browse files
Add array_get and array_has functions
1 parent f907571 commit 952d028

File tree

4 files changed

+138
-5
lines changed

4 files changed

+138
-5
lines changed

ext/standard/array.c

Lines changed: 108 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -6910,6 +6910,114 @@ PHP_FUNCTION(array_key_exists)
69106910
}
69116911
/* }}} */
69126912

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

ext/standard/basic_functions.stub.php

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

1906+
/**
1907+
* @compile-time-eval
1908+
*/
1909+
function array_get(array $array, string|int|null $key = null, mixed $default = null): mixed {}
1910+
1911+
/**
1912+
* @compile-time-eval
1913+
*/
1914+
function array_has(array $array, string|int $key): bool {}
1915+
19061916
/**
19071917
* @compile-time-eval
19081918
*/

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)