PHP 服務端模板渲染時將變量傳給前端 JavaScript,是傳統 MVC 應用的核心模式。本文系統梳理**模板內聯輸出、JSON 配置物件、AJAX 異步獲取**三大模式,重點解決「陣列/物件序列化、XSS 防護、類型保真、CSP 兼容」等實戰難點。
<?php
// Controller
$user = [
'id' => 123,
'name' => 'Alice & Bob', // 含特殊字符
'roles' => ['admin', 'editor'],
'settings' => (object)['theme' => 'dark', 'lang' => 'zh-CN'],
];
$initialState = [
'user' => $user,
'csrfToken' => bin2hex(random_bytes(32)),
'apiBase' => 'https://api.example.com/v1',
];
require 'view.php';
?>
Dashboard
Loading...
// 解析初始狀態
const initialState = JSON.parse(document.getElementById('initial-state').textContent);
const { user, csrfToken, apiBase } = initialState;
console.log(user.name); // "Alice & Bob" (正確保留,未被轉義為實體)
// 直接可用於 Vue/React 初始化 store、React Query cache 等
<?php
$config = [
'env' => 'production',
'debug' => false,
'version' => '2.4.1',
'features' => ['newDashboard' => true, 'betaApi' => false],
'cdnUrl' => 'https://cdn.example.com',
];
?>
<?php
// api/user.php
header('Content-Type: application/json; charset=UTF-8');
session_start();
if (empty($_SESSION['user_id'])) {
http_response_code(401);
echo json_encode(['error' => 'Unauthorized']);
exit;
}
$user = getUserById($_SESSION['user_id']);
// 移除敏感字段
unset($user['password_hash'], $user['email_verified_at']);
echo json_encode($user, JSON_UNESCAPED_UNICODE);
?>
// 前端
async function fetchCurrentUser() {
const resp = await fetch('/api/user.php', {
credentials: 'include', // 攜帶 Cookie
headers: { 'Accept': 'application/json' }
});
if (!resp.ok) throw new Error(`HTTP ${resp.status}`);
return resp.json();
}
// 使用
const user = await fetchCurrentUser();
PHP `int`/`float` → JSON number → JS `number` (IEEE 754 雙精度)。**大整數 (> 2^53-1) 會失去精度**。
<?php
$bigId = 1234567890123456789; // 超過 2^53
echo json_encode(['id' => $bigId]); // {"id":1234567890123456789} 但 JS 解析為 1234567890123456800
// 解決:大整數作為字串輸出
echo json_encode(['id' => (string)$bigId], JSON_UNESCAPED_UNICODE);
// {"id":"1234567890123456789"} -> JS 端用 BigInt 或字串比較
?>
<?php
$dt = new DateTimeImmutable('now', new DateTimeZone('UTC'));
echo json_encode(['created_at' => $dt->format(DateTime::ATOM)]);
// {"created_at":"2024-01-15T14:30:00+00:00"}
// JS 端: new Date(data.created_at) 直接解析
?>
<?php
// 禁止 inline script,只允許外部文件
header("Content-Security-Policy: script-src 'self' https://cdn.example.com; object-src 'none'; base-uri 'self';");
// 模式一 的 違反 CSP,需改為:
// 1. 獨立文件 config.js.php 動態生成 (加快快取)
// 2. 或用 + JS 解析
?>
<form id="profile-form">
</form>
<script>
// JS 即時驗證
document.getElementById('profile-form').addEventListener('submit', async (e) => {
e.preventDefault();
const formData = new FormData(e.target);
const resp = await fetch('/api/profile.php', {
method: 'POST',
body: formData,
credentials: 'include',
});
const result = await resp.json();
if (result.errors) {
Object.entries(result.errors).forEach(([field, msg]) => {
document.querySelector(`[data-for="${field}"]`).textContent = msg;
});
} else {
alert('保存成功');
}
});
</script>
| 場景 | 推薦模式 | 關鍵點 |
|---|---|---|
| 首屏渲染數據、SEO 內容、初始化 Store | 模式一:`
Copyright © 程式碼之家 All Rights Reserved
|