對於較早版本的 PHP,您可以使用以下程式碼片段來 polyfill `str_contains` 函式
<?php
// 基於 PHP Laravel 框架的原始程式碼
if (!function_exists('str_contains')) {
function str_contains($haystack, $needle) {
return $needle !== '' && mb_strpos($haystack, $needle) !== false;
}
}
?>
(PHP 8)
str_contains — 判斷字串是否包含指定的子字串
haystack
要在其中搜尋的字串。
needle
要在 haystack
中搜尋的子字串。
範例 #1 使用空字串 ''
<?php
if (str_contains('abc', '')) {
echo "Checking the existence of the empty string will always return true";
}
?>
以上範例會輸出
Checking the existence of the empty string will always return true
範例 #2 顯示區分大小寫
<?php
$string = 'The lazy fox jumped over the fence';
if (str_contains($string, 'lazy')) {
echo "The string 'lazy' was found in the string\n";
}
if (str_contains($string, 'Lazy')) {
echo 'The string "Lazy" was found in the string';
} else {
echo '"Lazy" was not found because the case does not match';
}
?>
以上範例會輸出
The string 'lazy' was found in the string "Lazy" was not found because the case does not match
注意:此函式是二進位安全的。
對於較早版本的 PHP,您可以使用以下程式碼片段來 polyfill `str_contains` 函式
<?php
// 基於 PHP Laravel 框架的原始程式碼
if (!function_exists('str_contains')) {
function str_contains($haystack, $needle) {
return $needle !== '' && mb_strpos($haystack, $needle) !== false;
}
}
?>
這個基於 PHP Laravel 框架原始程式碼的 polyfill 表現行為有所不同;
當 $needle 為 `""` 或 `null` 時
php8 會回傳 `true`;
但 Laravel 的 str_contains 會回傳 `false`;
在 php8.1 中,null 已被棄用,您可以使用 `$needle ?: ""`;
幾個用於檢查字串是否包含陣列中任何字串或所有字串的函式
<?php
function str_contains_any(string $haystack, array $needles): bool
{
return array_reduce($needles, fn($a, $n) => $a || str_contains($haystack, $n), false);
}
function str_contains_all(string $haystack, array $needles): bool
{
return array_reduce($needles, fn($a, $n) => $a && str_contains($haystack, $n), true);
}
?>
如果 $needles 是一個空陣列,str_contains_all() 會回傳 true。如果您認為這是錯誤的,請在 $needles 中顯示一個「沒有」出現在 $haystack 中的字串,然後查閱「虛真」(vacuous truth)。
(透過在這些函式的程式碼主體中交換 haystack 和 needles,您可以建立檢查 needle 是否出現在任何/所有 haystack 陣列中的版本。)
如果您有一個非 UTF-8 編碼的 needle,但在 UTF-8 字串中搜尋它,這個函式並不總是產生預期的結果。這對大多數人來說不是問題,但如果您混合了舊資料和新資料,尤其是在從檔案讀取資料時,這可能會是一個問題。
這裡有一個類似 "mb_*" 的函數,用於搜尋字串
<?php
function mb_str_contains(string $haystack, string $needle, $encoding = null) {
return $needle === '' || mb_substr_count($haystack, $needle, (empty($encoding) ? mb_internal_encoding() : $encoding)) > 0;
}
?>
我使用 mb_substr_count() 而不是 mb_strpos(),因為 mb_strpos() 仍然會匹配部分字元,因為它執行的是二進位搜尋。
我們可以將 str_contains 與上面建議的函數進行比較
<?php
// 一些 Unicode 漢字(漢字はユニコード)
$string = hex2bin('e6bca2e5ad97e381afe383a6e3838be382b3e383bce38389');
// 一些 Windows-1252 字元 (ãƒ)
$contains = hex2bin('e383');
// ^ 使用 Windows 記事本以「ANSI」編碼儲存檔案時,file_get_contents() 會產生相同的資料,所以這並非不切實際的情況。這裡使用 hex2bin 的唯一原因是在不使用多個檔案的情況下混合字元集。
// 實際存在於我們字串中的字元。(ー)
$contains2 = hex2bin('e383bc');
echo " = 母字串: ".var_export($string, true)."\r\n";
echo " = 子字串:\r\n";
echo " + Windows-1252 字元\r\n";
echo " - 結果:\r\n";
echo " > str_contains: ".var_export(str_contains($string, $contains), true)."\r\n";
echo " > mb_str_contains: ".var_export(mb_str_contains($string, $contains), true)."\r\n";
echo " + 有效的 UTF-8 字元\r\n";
echo " - 結果:\r\n";
echo " > str_contains: ".var_export(str_contains($string, $contains2), true)."\r\n";
echo " > mb_str_contains: ".var_export(mb_str_contains($string, $contains2), true)."\r\n";
echo "\r\n";
?>
輸出
= 母字串: '漢字はユニコード'
= 子字串
+ Windows-1252 字元
- 結果
> str_contains: true
> mb_str_contains: false
+ 有效的 UTF-8 字元
- 結果
> str_contains: true
- 結果
然而,這並非完全萬無一失。例如,Windows-1252 編碼中的 ド 會與上述字串中的 ド 匹配。因此,最好還是先將參數的編碼轉換成相同的編碼。但是,如果字元集未知/無法檢測,而且您不得不處理雜亂的資料,這可能是最簡單的解決方案。
如果單詞位於以下位置,「me at daz dot co dot uk」的程式碼將無法運作:
- 字串的開頭
- 字串的結尾
- 句子的結尾(例如「the ox.」或「is that an ox?」)
- 引號內
- 等等。
您應該使用空格、標點符號等將字串拆分,並檢查產生的陣列是否包含您的單詞,或者嘗試使用如下所示的正規表達式進行測試
(^|[\s\W])+word($|[\s\W])+
免責聲明:此正規表達式可能需要一些調整
private function contains(array $needles, string $type, string $haystack = NULL, string $filename = NULL) : bool {
if (empty($needles)) return FALSE;
if ($filename)
$haystack = file_get_contents($filename);
$now_what = function(string $needle) use ($haystack, $type) : array {
$has_needle = str_contains($haystack, $needle);
if ($type === 'any' && $has_needle)
return ['done' => TRUE, 'return' => TRUE];
if ($type === 'all' && !$has_needle)
return ['done' => TRUE, 'return' => FALSE];
return ['done' => FALSE];
};
foreach ($needles as $needle) {
$check = $now_what($needle);
if ($check['done'])
return $check['return'];
}
return TRUE;
}
function containsAny(array $needles, string $haystack = NULL, string $filename = NULL) : bool {
return self::contains($needles, 'any', $haystack, $filename);
}
function containsAll(array $needles, string $haystack = NULL, string $filename = NULL) : bool {
return self::contains($needles, 'all', $haystack, $filename);
}
<?php
// 適用於 PHP 4 - PHP 7 的 Polyfill,可安全地與 PHP 8 一起使用
if (!function_exists('str_contains')) {
function str_contains (string $haystack, string $needle)
{
return empty($needle) || strpos($haystack, $needle) !== false;
}
}