從模板渲染、API 響應、日誌記錄、數據庫查詢構建,到协议封裝,字符串操作無處不在。PHP 作為弱類型語言,提供了極其豐富且靈活的字符串函數族。本文系統梳理核心特性、引號語義差異、輸出函數對比、格式化家族,並提供性能與安全最佳實踐。
PHP 內部使用 zval 統一表示變量,字符串函數接受任意類型參數,自動按上下文轉換:
<?php
echo substr("123456", 1, 3); // "234"
echo substr(123456, 1, 3); // "234" 整數自動轉字符串
echo substr(1.23e2, 1, 3); // "23" 浮點數轉科學計數法字符串
echo substr(true, 1, 3); // "ru" 布爾值轉 "1" / ""
echo substr([1,2], 1, 3); // Warning: Array to string conversion → "Array"
?>
建議:顯式轉換 (string)$val 或 strval($val),避免隱式行為差異。
| 特性 | 單引號 '...' | 雙引號 "..." |
|---|---|---|
| 變量解析 | ❌ 字面量 | ✅ 解析變量 |
| 轉義序列 | 僅 \' \\ | 完整支持 \n \t \r \$ \" 等 |
| 性能 | 極快(無解析) | 稍慢(需掃描解析) |
| 適用場景 | 純靜態文本、正則模板、大量字符串拼接 | 需插值的模板、包含換行/制表的文本 |
<?php
$name = 'World';
echo 'Hello $name\n'; // Hello $name\n (字面輸出)
echo "Hello $name\n"; // Hello World
// (換行)
$price = 19.9;
echo "Price: \$$price"; // Price: $19.9 (轉義 $ 符號)
echo 'Price: $' . $price; // 單引號拼接更快
?>
$arr = ['user' => ['name' => 'Tom']];
echo "Name: {$arr['user']['name']}"; // 正確
echo "Name: ${arr['user']['name']}"; // 正確
// echo "Name: $arr['user']['name']"; // 錯誤:解析為 $arr['user'] . 'name'
| 函數 | 類型 | 返回值 | 多參數 | 格式化 | 速度 | 適用場景 |
|---|---|---|---|---|---|---|
echo | 語言構造 | 無 | ✅ echo $a, $b | ❌ | 最快 | 通用輸出 |
print | 語言構造 | 總是 1 | ❌ | ❌ | 稍慢 | 需返回值的表達式上下文 |
printf | 函數 | 輸出長度 | ❌ | ✅ %s %d %f | 慢 | 格式化輸出 |
sprintf | 函數 | 格式化字符串 | ❌ | ✅ | 慢 | 構建格式化字符串 |
vprintf/vsprintf | 函數 | 同上 | 數組參數 | ✅ | 慢 | 動態參數列表 |
fprintf | 函數 | 寫入長度 | 流資源 | ✅ | 慢 | 寫入文件/流 |
<?php
// print 可用於表達式上下文
$flag = false;
$flag or print "Error!"; // 合法,輸出 Error! 並返回 1
// $flag or echo "Error!"; // Parse error: echo 不能用於表達式
// echo 支持多參數(無拼接開銷)
echo "A", "B", "C"; // 直接依次輸出
// print "A", "B"; // 語法錯誤
// sprintf 構建字符串
$sql = sprintf("SELECT * FROM %s WHERE id = %d AND status = '%s'",
'users', 123, 'active');
// 避免手動拼接注入風險,但請優先用預處理語句
?>
<?php
$name = 'PHP';
$str = <<format('Y-m-d')}.
</div>
HTML;
// 結束標譤必須頂格寫,前後無空白
?>
$str = <<<'SQL'
SELECT * FROM users
WHERE name = '$name' -- 變量不解析
AND status = 'active'
SQL;
| 分類 | 高頻函數 | 用途 |
|---|---|---|
| 查找/替換 | strpos/stripos | 查找位置(大小寫敏感/不敏感) |
str_replace/str_ireplace | 替換(支援數組批量) | |
substr_replace | 指定位置替換 | |
| 截取/分割 | substr/mb_substr | 截取(多字節必須用 mb_*) |
explode/str_split | 分割為數組 | |
preg_split | 正則分割 | |
| 大小寫/格式 | strtolower/strtoupper | 轉換(多字節用 mb_*) |
ucfirst/ucwords | 首字母/單詞首字母大寫 | |
trim/ltrim/rtrim | 去除首尾空白/指定字符 | |
| 編碼/轉義 | htmlspecialchars/htmlentities | HTML 實體轉義(防 XSS 必用) |
addslashes/stripslashes | 反斜杠轉義/移除 | |
json_encode/json_decode | JSON 序列化(現代首選) | |
| 比較/匹配 | strcmp/strcasecmp | 二進制安全比較 |
strnatcmp/strnatcasecmp | 自然排序比較 | |
similar_text/levenshtein | 相似度/編輯距離 |
<?php
// 內部編碼設置(腳本頂部/啟動文件)
mb_internal_encoding('UTF-8');
mb_regex_encoding('UTF-8');
$zh = '你好世界';
// ❌ 錯誤:substr 按字節截取,破壞多字節字符
echo substr($zh, 0, 3); // ""
// ✅ 正確:mb_substr 按字符截取
echo mb_substr($zh, 0, 2); // "你好"
// 正則也需 mb_ 前綴或 u 修飾符
preg_match('/^.{2}/u', $zh, $m); // $m[0] = "你好"
mb_ereg('^.{2}', $zh, $m); // 同樣效果
?>
$str .= $part 或 implode('', $parts),避免 $str = $str . $part 重複複製strpos/str_replace,C 級實現比 PCRE 快 10-100 倍preg_match 時,模式固定可獲益於 PCRE 緩存echo 或輸出緩衝 ob_start()htmlspecialchars($str, ENT_QUOTES, 'UTF-8') 防 XSSaddslashes/mysql_real_escape_string,**強制使用預處理語句**escapeshellarg/escapeshellcmd,或優先用 proc_open 繞過 Shellbasename/realpath 驗證用戶輸入路徑PHP 字符串系統以弱類型自動轉換、雙引號插值、豐富函數族著稱。掌握引號語義邊界、輸出函數選型、多字節處理、格式化家族,配合性能優先原則(單引號、拼接優化、避免正則)與安全紅線(輸出轉義、預處理、命令轉義),能寫出高效、安全、可維護的字符串處理代碼。