在控制器直接 echo 或 $this->success() 後輸出 <script>,瀏覽器卻只顯示純文字 window.top.location.href='...',標籤被吞噬。
ThinkPHP 模板引擎 (或輸出過濾機制) 會對輸出內容進行標籤解析/過濾。控制器直接輸出的 <script> 被視為模板標籤而被移除或轉義。
<literal> 包裹<?php
// 錯誤示範
echo "<script>window.top.location.href='{$url}';</script>";
// 輸出變成:window.top.location.href='...'; (標籤消失)
// 正確做法
echo '<literal><script>alert("退出成功");top.location.href="login";</script></literal>';
<?php
class AuthController extends Controller {
public function logout() {
session('[destroy]');
$url = U('Login/index');
// 使用 literal 確保 script 標籤完整輸出到瀏覽器執行
echo '<literal><script>parent.location.href="' . $url . '";</script></literal>';
exit;
}
}
| 方案 | 優點 | 缺點 |
|---|---|---|
<literal> 包裹 | 零改動、相容現有邏輯 | 需記得加標籤 |
模板檔 success.html 內寫 JS | 關注點分離 | 需修改跳轉模板 |
| AJAX 回應 JSON + 前端處理跳轉 | 現代 SPA 模式、體驗佳 | 需前端配合改造 |
HTTP Header Location 重導向 | 無 JS 依賴 | 無法跨 frame (top) 跳轉 |
{url: '...'},前端統一處理跳轉。<literal>。$this->success(),自訂 Public/success.html 內寫 <script>parent.location='{$jumpUrl}';</script> 更乾淨。