PHP 服務端渲染頁面時,常需將變量傳遞給前端 JavaScript。核心機制是 PHP 在輸出階段將變量值「內插」到 JS 代碼字符串中,瀏覽器接收到的是純文本 JS。本文詳細講解安全輸出模式、數據類型對應、條件分支編譯陷阱與現代最佳實踐。
<?php
$title = '首頁 & 儀表盤';
$userCount = 12345;
$tags = ['php', 'js', 'ajax'];
$flags = true;
?>
<script>
// 字符串:必須用 json_encode 自動加引號、轉義
var title = <?= json_encode($title, JSON_HEX_TAG | JSON_HEX_APOS | JSON_HEX_QUOT | JSON_HEX_AMP) ?>;
// 數字/布爾:直接輸出
var userCount = <?= $userCount ?>;
var flags = <?= $flags ? 'true' : 'false' ?>;
// 數組/對象:json_encode 輸出 JS 字面量
var tags = <?= json_encode($tags) ?>;
console.log(title, userCount, flags, tags);
</script>
json_encode?| PHP 類型 | 直接 echo 後果 | json_encode 結果 | 說明 |
|---|---|---|---|
| 字符串含引號/換行 | JS 語法錯誤 | "Hello \"World\"" | 自動轉義、加雙引號 |
| 關聯數組 | Array to string notice | {"key":"val"} | 轉為 JS 對象 |
| 索引數組 | 同上 | ["a","b"] | 轉為 JS 數組 |
| null/false/true | 空字符串/0/1 | null/false/true | 保留 JS 原生字面量 |
| 浮點數 | 科學計數法風險 | 1.23 | 精度穩定 |
<?php
$flag = true;
if ($flag) {
$arr = ['a', 'b'];
} else {
$str = 'fallback';
}
?>
<script>
var flag = <?= $flag ? 'true' : 'false' ?>;
if (flag) {
var data = <?= json_encode($arr) ?>; // 正常
} else {
// 雖然不執行,但 PHP 編譯階段仍會解析此行
var data = <?= json_encode($str) ?>; // 若 $str 未定義或類型不符,這裡可能報錯
}
</script>
解決:確保所有分支變量在 PHP 端都已定義且類型兼容,或用三元運算符統一輸出:
var data = <?= json_encode($flag ? $arr : ['fallback']) ?>;
<script id="page-data" type="application/json"><?= json_encode([
'user' => $currentUser,
'config' => $siteConfig,
'csrfToken' => $_SESSION['csrf_token'],
], JSON_HEX_TAG | JSON_HEX_APOS | JSON_HEX_QUOT | JSON_HEX_AMP) ?></script>
<script>
const pageData = JSON.parse(document.getElementById('page-data').textContent);
console.log(pageData.user.name);
</script>
優點:HTML 與 JS 解耦、CSP 友好(script[type="application/json"] 不執行)、易維護。
// /api/page-init.php
header('Content-Type: application/json');
echo json_encode(['user' => $user, 'config' => $config]);
// 前端
fetch('/api/page-init.php').then(r => r.json()).then(data => { /* ... */ });
json_encode($val, JSON_HEX_TAG | JSON_HEX_APOS | JSON_HEX_QUOT | JSON_HEX_AMP) 防止 </script>、單雙引號、& 注入。Content-Security-Policy: script-src 'self'; object-src 'none'; 禁止內聯腳本執行(需配合 Nonce/Hash)。eval()/new Function() 解析服務端數據。@json($var) 自動帶安全標誌。{{ var|json_encode(constant('JSON_HEX_TAG|JSON_HEX_APOS|JSON_HEX_QUOT|JSON_HEX_AMP')) }}。{$var|json_encode}(需註冊修飾器)。總結:永遠用 json_encode 輸出 JS 變量,採用數據島模式分離關注點,配合 CSP 構建安全的 PHP-JS 交互邊界。