Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 2 additions & 0 deletions NEWS
Original file line number Diff line number Diff line change
Expand Up @@ -193,6 +193,8 @@ PHP NEWS
. bindec(), octdec(), hexdec() and base_convert() now throw an Exception
when the passed string contains characters that are invalid for the
specified number base. (Sjoerd Langkemper)
. Improved performance of in_array() and array_search() in strict mode when
searching for a string. (Alexander Danilov)

- URI:
. Fix casing of enum cases in UriHostType and UrlHostType to match the RFC
Expand Down
2 changes: 2 additions & 0 deletions UPGRADING
Original file line number Diff line number Diff line change
Expand Up @@ -206,6 +206,8 @@ PHP 8.7 UPGRADE NOTES
UTF-8.
. htmlspecialchars() returns its input without copying it when nothing needs
encoding.
. Improved performance of in_array() and array_search() in strict mode when
searching for a string.

- MBString:
. Improved performance of mb_strlen for UTF-8 strings.
Expand Down
16 changes: 16 additions & 0 deletions ext/standard/array.c
Original file line number Diff line number Diff line change
Expand Up @@ -1601,6 +1601,22 @@ static zend_always_inline void _php_search_array(zval *return_value, zval *value
}
}
} ZEND_HASH_FOREACH_END();
} else if (Z_TYPE_P(value) == IS_STRING) {
zend_string *needle = Z_STR_P(value);
ZEND_HASH_FOREACH_KEY_VAL(Z_ARRVAL_P(array), num_idx, str_idx, entry) {
ZVAL_DEREF(entry);
if (Z_TYPE_P(entry) == IS_STRING && zend_string_equals(Z_STR_P(entry), needle)) {
if (behavior == 0) {
RETURN_TRUE;
} else {
if (str_idx) {
RETURN_STR_COPY(str_idx);
} else {
RETURN_LONG(num_idx);
}
}
}
} ZEND_HASH_FOREACH_END();
} else {
ZEND_HASH_FOREACH_KEY_VAL(Z_ARRVAL_P(array), num_idx, str_idx, entry) {
ZVAL_DEREF(entry);
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,89 @@
--TEST--
in_array()/array_search() strict mode with a string needle
--FILE--
<?php

function dyn(string $s): string { return $s . ''; }

echo "-- found / not found --\n";
$list = ['alpha', 'beta', '', "a\0b", 'kappa'];
var_dump(in_array('kappa', $list, true));
var_dump(in_array('nope', $list, true));
var_dump(in_array('', $list, true));
var_dump(in_array("a\0b", $list, true));
var_dump(in_array("a\0c", $list, true));
var_dump(in_array('alph', $list, true));
var_dump(array_search('beta', $list, true));
var_dump(array_search('nope', $list, true));

echo "-- non-interned strings --\n";
var_dump(in_array(dyn('beta'), $list, true));
var_dump(in_array('beta', [dyn('beta')], true));
var_dump(array_search(dyn('kappa'), [dyn('kappa')], true));

echo "-- string and integer keys --\n";
var_dump(array_search('b', ['x' => 'a', 'y' => 'b', 7 => 'c'], true));
var_dump(array_search('c', ['x' => 'a', 'y' => 'b', 7 => 'c'], true));

echo "-- elements of other types never match --\n";
var_dump(in_array('1', [1, 1.0, true, [1], null], true));
var_dump(in_array('', [null, false, 0, []], true));
var_dump(in_array('abc', [0, true, new stdClass], true));
var_dump(array_search('1', [1, '1'], true));

echo "-- references --\n";
$s = 'ref';
$arr = [1, &$s, 3];
var_dump(array_search('ref', $arr, true));
$s = 'changed';
var_dump(in_array('ref', $arr, true));
var_dump(array_search('changed', $arr, true));
$i = 5;
var_dump(in_array('5', ['a', &$i], true));

echo "-- holes --\n";
$packed = ['a', 'b', 'c'];
unset($packed[1]);
var_dump(in_array('b', $packed, true));
var_dump(array_search('c', $packed, true));
$hash = ['x' => 'a', 'y' => 'b'];
unset($hash['x']);
var_dump(array_search('b', $hash, true));

echo "-- empty array --\n";
var_dump(in_array('a', [], true));

?>
--EXPECT--
-- found / not found --
bool(true)
bool(false)
bool(true)
bool(true)
bool(false)
bool(false)
int(1)
bool(false)
-- non-interned strings --
bool(true)
bool(true)
int(0)
-- string and integer keys --
string(1) "y"
int(7)
-- elements of other types never match --
bool(false)
bool(false)
bool(false)
int(1)
-- references --
int(1)
bool(false)
int(1)
bool(false)
-- holes --
bool(false)
int(2)
string(1) "y"
-- empty array --
bool(false)
Loading