某企業的內部管理網站在搬遷至新主機後,前台頁面大致可以正常開啟,但進入後台訂單與資料列表時,DataTables 跳出以下錯誤:
DataTables warning: table id=dayTable - Invalid JSON response
由於舊主機原本可以正常使用,客戶一開始懷疑是新主機缺少套件、資料庫沒有完整匯入,或 DataTables 與新版 PHP 不相容。
實際檢查後發現,DataTables 本身沒有損壞,資料庫也能正常查詢。真正原因是 PHP 執行時產生 Notice,並將錯誤文字輸出在 JSON 前面,導致前端無法解析回傳資料。
案例重點:前端顯示 Invalid JSON,不代表 JavaScript 套件故障。只要後端回傳內容混入任何非 JSON 文字,DataTables 就可能無法載入。
網站環境與搬遷背景
- 企業內部使用的 PHP 後台系統。
- 後台列表使用 jQuery DataTables。
- 資料來源由 PHP 透過 AJAX 回傳 JSON。
- 網站由舊 cPanel 主機搬遷至新的 Linux 主機。
- PHP 版本與原主機設定略有差異。
- MySQL 資料已完成匯入。
搬遷完成後,網站首頁與登入功能正常,因此初步看起來不像整個 PHP 環境故障。
但只要進入使用 DataTables 的列表頁面,表格就無法顯示資料。
客戶遇到的實際症狀
- 後台頁面本身可以正常開啟。
- DataTables 表格持續顯示載入中。
- 畫面跳出 Invalid JSON response。
- 資料庫內確實有資料。
- 沒有明顯的 PHP Fatal error 畫面。
- 舊主機執行相同程式時正常。
由於 DataTables 是透過 AJAX 另外取得資料,所以頁面本身正常,不代表提供資料的 PHP 程式也正常。
1)先查看瀏覽器 Network 回傳內容
排查這類問題時,第一步不是重新安裝 DataTables,而是開啟瀏覽器開發者工具。
在 Chrome 中可以按下 F12,進入:
Network → Fetch/XHR
接著重新整理列表頁,找到 DataTables 呼叫的 PHP 檔案,再查看 Response。
正常的 DataTables JSON 回傳應該類似:
{ "draw": 1, "recordsTotal": 0, "recordsFiltered": 0, "data": [] }
但本次案例實際回傳內容是:
<br /> <b>Notice</b>: session_start(): Ignoring session_start() because a session is already active in /home/account/public_html/includes/config.php on line 3 <br /> {"draw":1,"recordsTotal":0,"recordsFiltered":0,"data":[]}
JSON 本身其實沒有錯,但前面多了一段 PHP Notice 與 HTML 標籤,DataTables 收到後便無法把整段內容解析成 JSON。
2)確認問題是重複執行 session_start
錯誤訊息指出,PHP Session 已經啟動,但程式又執行了一次:
session_start();
進一步檢查程式結構後發現:
- 主程式開頭已執行 session_start。
- 主程式接著載入共用設定檔。
- 共用設定檔內又執行一次 session_start。
- 新主機的 PHP 錯誤顯示設定較明確,因此 Notice 被直接輸出。
舊主機可能因為錯誤顯示關閉,所以相同程式雖然也存在問題,卻沒有把 Notice 顯示在畫面上。
判斷:這不是搬家造成的新程式錯誤,而是原本就存在的問題,在新主機環境中被顯示出來。
3)修正 Session 啟動方式
處理方式不是單純把錯誤隱藏,而是避免 Session 被重複啟動。
原本程式:
<?php session_start();
調整為:
<?php if (session_status() !== PHP_SESSION_ACTIVE) { session_start(); }
或者重新整理程式載入順序,讓整個系統只在固定的入口執行一次 session_start。
如果多個 PHP 檔案都會載入同一個設定檔,也應使用:
require_once include_once
避免設定檔被重複載入。
4)確保 AJAX 只回傳 JSON
DataTables 的資料來源程式應只輸出 JSON,不應混入:
- PHP Notice。
- PHP Warning。
- 除錯用的 echo。
- var_dump。
- HTML 標籤。
- 登入頁內容。
- 檔案前後的多餘文字。
回傳前可以明確設定 Content-Type:
header('Content-Type: application/json; charset=utf-8');
再使用:
echo json_encode($result, JSON_UNESCAPED_UNICODE); exit;
修正後,實際回傳內容恢復為:
{"draw":1,"recordsTotal":0,"recordsFiltered":0,"data":[]}
DataTables 隨即可以正常載入。
5)錯誤不能顯示,但仍應寫入 Log
正式網站的 AJAX 與 API 不適合直接顯示 PHP 錯誤,否則除了破壞 JSON,也可能洩漏主機路徑與程式資訊。
正式環境可將錯誤顯示關閉:
display_errors = Off log_errors = On
但不應把錯誤完全忽略,而是讓 PHP 寫入錯誤紀錄。
可以透過主機控制面板或 PHP 設定確認 error_log 位置,再定期檢查:
tail -100 error_log
這樣既不會把錯誤輸出給前端,也能保留排查依據。
6)同類型 Invalid JSON 還有哪些常見原因?
本次案例是 session_start Notice,但 DataTables Invalid JSON 還可能由以下問題造成:
- 資料庫連線失敗。
- SQL 查詢錯誤。
- 欄位不存在。
- 登入逾時後回傳整頁登入畫面。
- PHP Fatal error。
- JSON 中含有無法處理的字元。
- 程式輸出 UTF-8 BOM。
- 回傳資料包含 NAN 或 INF。
- 程式在 JSON 前執行 var_dump。
- 權限不足時被重新導向。
因此看到 Invalid JSON 時,最有效率的方法仍然是直接查看 AJAX Response,而不是猜測 DataTables 設定。
7)修正後的驗證項目
修正完成後,除了確認表格能顯示,還進一步檢查:
- AJAX Response 是否為合法 JSON。
- Response Header 是否為 application/json。
- PHP 錯誤紀錄是否仍產生 Notice。
- 分頁功能是否正常。
- 搜尋與排序是否正常。
- 不同登入權限是否正常。
- 資料筆數是否與資料庫一致。
- 登入逾時時是否回傳合理錯誤。
避免只看到第一頁有資料,就認為整個功能已經完成修復。
處理結果
- 移除重複 Session 啟動問題。
- AJAX 不再輸出 PHP Notice。
- DataTables 恢復正常載入。
- 搜尋、排序與分頁功能正常。
- PHP 錯誤改為寫入 Log。
- 保留搬遷前後的修改紀錄。
本次處理不需要重寫 DataTables,也不需要更換資料庫或重新製作後台。找到真正的回傳內容後,問題就能明確定位。
從這個案例可以得到什麼經驗?
- 頁面能開啟,不代表 AJAX 程式正常。
- Invalid JSON 通常要先看 Network Response。
- 網站搬遷會讓原本被隱藏的錯誤浮現。
- 正式環境不應直接顯示 PHP Notice。
- 關閉 display_errors 不等於問題已修好。
- JSON API 必須避免任何多餘輸出。
- 主機搬遷後應逐項驗證前台、後台、排程與 API。