字串處理是 PHP 開發最高頻操作。本文系統整理核心函式分類、參數陷阱、效能差異與現代最佳實踐 (PHP 8+)。
1. 拼接與插值
| 方式 | 語法 | 效能 | 說明 |
| 單引號 + `.` | 'Hello ' . $name | 極快 | 無解析,純拼接 |
| 雙引號插值 | "Hello $name" | 快 | 解析變數、逃逸序列 |
| Heredoc/Nowdoc | <<<EOT ... EOT | 中 | 多行字串、Nowdoc 不解析 |
| `sprintf()` | sprintf("Hello %s", $name) | 中 | 格式化控制、複雜模板 |
| `implode()` | implode(', ', $arr) | 快 | 陣列轉字串 |
**大量拼接**:用陣列收集最後 `implode()`,避免重複記憶體分配複製。
2. 計算長度與計數
<?php
$str = "Hello 世界";
strlen($str); // 11 (位元組長度)
mb_strlen($str, 'UTF-8'); // 8 (字元數,需 mbstring)
substr_count($str, 'l'); // 2 (子字串出現次數)
substr_count($str, 'lo', 1); // 從索引 1 開始找
str_word_count($str); // 2 (單詞數,英文為主)
str_word_count($str, 1); // ['Hello', '世界'] (單詞陣列)
str_word_count($str, 2); // [0=>'Hello', 6=>'世界'] (位置=>單詞)
?>
3. 查找與定位
| 函式 | 回傳 | 大小寫 | 多字元支援 | 備註 |
| `strpos($haystack, $needle, $offset=0)` | 索引 / false | 敏感 | 否 (位元組) | 最快,**嚴格用 `!== false` 判斷** |
| `stripos()` | 索引 / false | **不敏感** | 否 | 內部轉小寫再找 |
| `mb_strpos()` | 索引 / false | 敏感 | **是** | 指定編碼,正確處理中文 |
| `strstr($haystack, $needle)` | 子字串 (含 needle 後) / false | 敏感 | 否 | 找到後剩餘部分 |
| `stristr()` | 子字串 / false | 不敏感 | 否 | |
| `strrpos()` / `strripos()` | 最後出現索引 | 敏感/不敏感 | 否 | 反向查找 |
4. 子字串擷取與替換
<?php
$str = "Hello World";
// 擷取
substr($str, 0, 5); // "Hello" (位元組)
mb_substr($str, 0, 5); // "Hello" (字元,安全)
// 替換
substr_replace($str, 'PHP', 6); // "Hello PHP" (從 6 開始替換到結尾)
substr_replace($str, 'PHP', 6, 5); // "Hello PHP" (替換 5 字元)
substr_replace($str, '!!!', -6); // "Hello !!!" (負數從尾部倒數)
// 批次替換
str_replace('World', 'PHP', $str); // "Hello PHP" (快、區分大小寫)
str_ireplace('world', 'PHP', $str); // "Hello PHP" (不區分大小寫)
preg_replace('/\d+/', '*', 'v1.2.3'); // "v*.*.*" (正則替換)
strtr($str, ['World'=>'PHP', 'Hello'=>'Hi']); // "Hi PHP" (單次掃描、最長優先、不重複替換)
?>
5. 字串比較
| 函式/運算子 | 行為 | 回傳 | 適用 |
| `==` / `===` | 值比較 / 型別+值 | bool | 簡單相等 |
| `strcmp($a, $b)` | 二進位比較 (ASCII 碼) | -1/0/1 | 精確排序、驗證 |
| `strcasecmp()` | 不分大小寫 strcmp | -1/0/1 | 忽略大小寫比較 |
| `strnatcmp()` | 自然排序比較 (數字大小) | -1/0/1 | 'file2' < 'file10' |
| `strnatcasecmp()` | 自然+不分大小寫 | -1/0/1 | 檔名排序 |
| `strncmp($a,$b,$len)` | 比較前 $len 字元 | -1/0/1 | 前綴比對 |
| `version_compare()` | 版本號比較 | -1/0/1 | PHP/套件版本 |
6. 分割與合併
<?php
// 分割
explode(',', 'a,b,c'); // ['a','b','c'] (固定分隔符,最快)
preg_split('/\s+/', 'a b c'); // ['a','b','c'] (正則,多空白)
str_split('abc', 2); // ['ab','c'] (固定長度)
mb_split('、', '一、二、三'); // 多字元分隔符
// 合併
implode(',', ['a','b','c']); // "a,b,c"
join('|', ['a','b']); // "a|b" (別名)
// 進階:CSV 解析
str_getcsv('"a,b",c'); // ['a,b', 'c'] (處理引號、逗號)
?>
7. 大小寫轉換與格式化
<?php
strtolower('HELLO'); // "hello"
strtoupper('hello'); // "HELLO"
ucfirst('hello world'); // "Hello world" (首字元)
ucwords('hello world'); // "Hello World" (每單詞首字元)
mb_convert_case('hELLO', MB_CASE_TITLE, 'UTF-8'); // "Hello" (多字元安全)
// 格式化
printf("Price: %.2f", 19.9); // 直接輸出
$fmt = sprintf("%04d", 7); // "0007" (回傳)
number_format(1234.56, 2, '.', ','); // "1,234.56" (千分位)
money_format('%.2n', 1234.56); // "$1,234.56" (需 locale、PHP 8.0+ 棄用)
?>
8. 編碼轉換與清理
<?php
// 編碼轉換
mb_convert_encoding($str, 'UTF-8', 'BIG-5'); // 指定來源編碼
iconv('BIG-5', 'UTF-8//IGNORE', $str); // IGNORE 跳過無效字元
// 清理
trim($str); // 移除首尾空白 (含 \n\r\t\v\0)
ltrim($str, '0'); // 移除首尾指定字元
strip_tags($str, ''); // 移除 HTML 標籤,保留允許標籤
htmlspecialchars($str, ENT_QUOTES, 'UTF-8'); // 轉義 HTML 實體 (防 XSS)
html_entity_decode($str); // 反向轉義
addslashes($str); // 反斜線轉義 (資料庫舊式)
stripslashes($str); // 移除反斜線
// 其它
str_repeat('*', 10); // "**********"
strrev('hello'); // "olleh"
chunk_split(base64_encode($data), 76, "\n"); // MIME 分行
wordwrap($longText, 80, "\n"); // 強制換行
?>
9. 正則表達式 (PCRE) 核心函式
<?php
preg_match('/\b\w{3}\b/', $str, $matches); // 單次匹配,$matches[0] 完整匹配,$matches[1] 第一捕獲組
preg_match_all('/\d+/', $str, $matches); // 所有匹配,$matches[0] 為全匹配陣列
preg_replace('/\s+/', ' ', $str); // 替換
preg_split('/[,;]/', 'a,b;c'); // 正則分割
preg_grep('/^error_/', $arr); // 陣列過濾
preg_quote($str, '/'); // 轉義正則特殊字元
?>
效能與最佳實踐摘要
- **固定字串操作優先用非正則函式** (`strpos` > `preg_match`、`str_replace` > `preg_replace`、`explode` > `preg_split`)。
- **多字元字串 (中文) 必須用 `mb_*` 系列**,指定 `internal_encoding` 或每呼叫傳編碼參數。
- **防 XSS**:輸出到 HTML **永遠** `htmlspecialchars($str, ENT_QUOTES, 'UTF-8')`。
- **資料庫參數化查詢** 取代 `addslashes`/`mysqli_real_escape_string`。
- **大量拼接**:`$parts[] = ...; $result = implode('', $parts);`。
- **PHP 8+ 新函式**:`str_contains($haystack, $needle)`、`str_starts_with()`、`str_ends_with()`、`str_decrement()`、`str_increment()`。