四種字串定義方式比較
| 語法 | 解析變數 | 解析跳脫序列 | 適用場景 |
單引號 '...' | 否 | 僅 \' \\ | 純靜態字串、效能最佳 |
雙引號 "..." | 是 | 完整 \n \t \r \$ \\ \" | 簡單插值、單行 |
Heredoc <<<EOT ... EOT; | 是 | 完整 | 多行、含引號、SQL、HTML 模板 |
Nowdoc <<<'EOT' ... EOT; | 否 | 否 | 多行靜態、正則、程式碼片段 |
雙引號 / Heredoc 插值語法細節
1. 簡單變數
$name = 'Alice';
echo "Hello $name!"; // Hello Alice!
2. 陣列元素:必須加花括號
$user = ['name' => 'Alice', 'age' => 30];
// 錯誤:遇到 [ 結束變數解析
echo "Name: $user[name]"; // Notice: Array to string conversion
echo "Name: $user['name']"; // 語法錯誤
// 正確:花括號包裹完整變數表達式
echo "Name: {$user['name']}"; // Name: Alice
echo "Age in 5 yrs: {$user['age'] + 5}"; // 35
3. 物件屬性
class User { public string $name = 'Alice'; }
$user = new User();
echo "Name: {$user->name}"; // 正確
echo "Name: $user->name"; // 也可,但花括號更明確
4. 複雜表達式(PHP 8.2+ 支援任意表達式)
$items = ['apple', 'banana', 'orange'];
echo "First: {$items[0]}"; // 陣列索引
echo "Count: {count($items)}"; // 函數呼叫
echo "Upper: {strtoupper($items[1])}"; // 巢狀函數
echo "JSON: {json_encode($items)}"; // 任意表達式
5. 變數名含特殊字元或動態名稱
$data = ['user-name' => 'Alice', 'user_age' => 30];
$key = 'user-name';
echo "Name: {$data[$key]}"; // 必須用花括號包裹陣列存取
// 變數變數
$var = 'name';
$name = 'Alice';
echo "{$var} = ${$var}"; // name = Alice (較少用,建議改用陣列)
Heredoc / Nowdoc 實戰範本
SQL 查詢
$sql = <<<SQL
SELECT u.id, u.name, u.email, p.title
FROM users u
JOIN posts p ON u.id = p.user_id
WHERE u.status = '{$status}'
AND u.created_at >= '{$startDate}'
ORDER BY u.id DESC
LIMIT {$limit}
SQL;
HTML 郵件模板
{$user['email']} 已啟用。</p>
<p>臨時密碼: {$tempPassword}</p>
<hr>
<small>此為系統自動發送,請勿回覆。</small>
</body>
</html>
HTML;
Nowdoc:正則、程式碼片段
效能與最佳實務
| 場景 | 推薦 | 理由 |
| 靜態字串、不含變數 | 單引號 | 無解析開銷、意圖明確 |
| 1-2 個變數、單行 | 雙引號 | 可讀性好、編譯期優化 |
| 多行、含引號、複雜插值 | Heredoc | 不需跳脫引號、縮排友善 |
| 大量字串拼接 | sprintf / implode / StringBuilder 模式 | 避免重複複製記憶體 |
| 模板引擎 | Twig / Blade / Latte | 關注點分離、快取、安全過濾 |
字串拼接效能陷阱
常見錯誤
- 陣列鍵未加花括號:
"$arr[key]" 會先解析常數 key,若未定義則警告並轉字串。永遠用 {$arr['key']}。
- Heredoc 結束標記縮排:結束標記必須頂格,前後不能有空白,否則不識別。
- 雙引號內直接寫類別常數:
"Value: Class::CONST" 不解析,需 "Value: {Class::CONST}" (PHP 8.2+)。
- Nowdoc 仍嘗試插值:Nowdoc 等同單引號,完全不解析,適合貼程式碼、正則。
總結
- 單引號靜態、雙引號簡單插值、Heredoc多行模板、Nowdoc原始碼片段。
- 陣列、物件、複雜表達式必須用花括號
{...} 包裹。
- 大量拼接用
implode 或 Generator,避免 .= 記憶體抖動。
- 複雜頁面改用模板引擎,PHP 專注資料準備。