The `str_contains` is not exact match with PHP 8.0+.
ve3 opened this issue · comments
Line 93 in 9b5ee6f
Tests code.
$string = '123abcกขคょよら㑆㑇㑈456.78';
echo 'haystack is ' . $string . '<br>';
echo 'false, true, empty<br>';
var_dump(str_contains($string, false));// true
var_dump(str_contains($string, true));// false
var_dump(str_contains($string, ''));// true
echo 'contains strings<br>';
var_dump(str_contains($string, 'a'));// true
var_dump(str_contains($string, 'aa'));// false
var_dump(str_contains($string, 'z'));// false
// thai
var_dump(str_contains($string, 'ก'));// true
var_dump(str_contains($string, 'กก'));// false
var_dump(str_contains($string, 'ฮ'));// false
// japanese
var_dump(str_contains($string, 'ょ'));// true
var_dump(str_contains($string, 'ょょ'));// false
var_dump(str_contains($string, 'ゖ'));// false
// chinese
var_dump(str_contains($string, '㑆'));// true
var_dump(str_contains($string, '㑆㑆'));// false
var_dump(str_contains($string, '㔩'));// false
echo 'contains 0 & 1 (int)<br>';
var_dump(str_contains($string, 0));// false
var_dump(str_contains($string, 1));// true
echo 'contains numbers (float, double)<br>';
var_dump(str_contains($string, 123.0));// true
var_dump(str_contains($string, 456.78));// true
echo 'haystack is true. check contains false, true, empty<br>';
var_dump(str_contains(true, false));// true
var_dump(str_contains(true, true));// true
var_dump(str_contains(true, ''));// true
echo 'haystack is false. check contains false, true, empty<br>';
var_dump(str_contains(false, false));// true
var_dump(str_contains(false, true));// false
var_dump(str_contains(false, ''));// true
echo 'haystack is empty. check contains false, true, empty<br>';
var_dump(str_contains('', false));// true
var_dump(str_contains('', true));// false
var_dump(str_contains('', ''));// true
echo 'error!<br>';
var_dump(str_contains($string, ['a']));
echo 'can\'t continue here.<br>';
The empty string and false
are always return true
.
The float (or double) type and true
have to check with mb_strpos()
instead of strpos()
to return the exactly same result with PHP 8.0+.
Here is my function I use.
if (!function_exists('str_contains')) {
function str_contains($haystack, $needle) {
// verify type and show the errors as in PHP 8.
if (!is_scalar($haystack)) {
trigger_error('Argument #1 ($haystack) must be of type string, ' . gettype($haystack) . ' given', E_USER_ERROR);
}
if (!is_scalar($needle)) {
trigger_error('Argument #2 ($needle) must be of type string, ' . gettype($needle) . ' given', E_USER_ERROR);
}
return '' === $needle || false === $needle || false !== mb_strpos($haystack, $needle);
}
}
Can you show where is the difference? The current version behaves exactly the same to me: https://3v4l.org/aFtVo
Weird, My tests before is different but currently they are same. I don't know why.
Maybe my mistake.
Here is new tests code. All are fine.
<?php
if (!function_exists('str_contains')) {
function str_contains(string $haystack, string $needle) {
return '' === $needle || false !== strpos($haystack, $needle);
}
}
$string = '123abcกขคょよら㑆㑇㑈456.78';
echo 'haystack is ' . var_export($string, true) . '<br>';
$tests = [
[
'testChar' => false,
'expected' => true,
],
[
'testChar' => true,
'expected' => true,
],
[
'testChar' => '',
'expected' => true,
],
// test with strings.=====
[
'testChar' => 'a',
'expected' => true,
],
[
'testChar' => 'aa',
'expected' => false,
],
[
'testChar' => 'z',
'expected' => false,
],
// Thai
[
'testChar' => 'ก',
'expected' => true,
],
[
'testChar' => 'กก',
'expected' => false,
],
[
'testChar' => 'ฮ',
'expected' => false,
],
// Japanese
[
'testChar' => 'ょ',
'expected' => true,
],
[
'testChar' => 'ょょ',
'expected' => false,
],
[
'testChar' => 'ゖ',
'expected' => false,
],
// Chinese
[
'testChar' => '㑆',
'expected' => true,
],
[
'testChar' => '㑆㑆',
'expected' => false,
],
[
'testChar' => '㔩',
'expected' => false,
],
// 0 & 1 (int) =====
[
'testChar' => 0,
'expected' => false,
],
[
'testChar' => 1,
'expected' => true,
],
// float (double) =====
[
'testChar' => 123.0,
'expected' => true,
],
[
'testChar' => 456.78,
'expected' => true,
],
];
runTests($string, $tests);
$string = true;
echo 'haystack is ' . var_export($string, true) . '<br>';
$tests = [
[
'testChar' => false,
'expected' => true,
],
[
'testChar' => true,
'expected' => true,
],
[
'testChar' => '',
'expected' => true,
],
];
runTests($string, $tests);
$string = false;
echo 'haystack is ' . var_export($string, true) . '<br>';
$tests = [
[
'testChar' => false,
'expected' => true,
],
[
'testChar' => true,
'expected' => false,
],
[
'testChar' => '',
'expected' => true,
],
];
runTests($string, $tests);
$string = '';
echo 'haystack is ' . var_export($string, true) . '<br>';
$tests = [
[
'testChar' => false,
'expected' => true,
],
[
'testChar' => true,
'expected' => false,
],
[
'testChar' => '',
'expected' => true,
],
];
runTests($string, $tests);
//echo 'must showing errors!<br>' . "\n";
//str_contains($string, ['a']);
function runTests($haystack, $tests)
{
foreach ($tests as $testItem) {
echo '<code>str_contains(' . var_export($haystack, true) . ', ' . var_export($testItem['testChar'], true) . ');</code><br>' . "\n";
echo ' expect: <code>' . var_export($testItem['expected'], true) . '</code><br>' . "\n";
$result = @str_contains($haystack, $testItem['testChar']);
echo ' got: <code>' . var_export($result, true) . '</code><br>' . "\n";
assert($testItem['expected'] === $result, 'Expect contains ' . var_export($testItem['testChar'], true) . ' to be ' . var_export($testItem['expected'], true) . ', Got ' . var_export($result, true) . '.');
}
unset($testItem);
}
Oh! I see that the function I use did not have string
type hint.
function str_contains($haystack, $needle)
That's why it returns different results.
The string
type hinting is since PHP 7+ as I remembered. I can't find document about this.
If you want to supported only PHP 7+ then it is okay but for those who use PHP 5.6 or older will get errors.