php – jQuery – AJAX 跨網域取得遠端 JSON 或 JSONP 設計
[更新 2017.03.02]
事隔三年,這兩天因為 Facebook 討論串的關係,發現有網友搜尋到這篇舊文章。今天發表了一篇較簡單、廢話沒這麼多的解決方法,可以點來看囉
jQuery – 在 header 修改,解決跨網域 JSON、JSONP 的方法
———————————————–
[事前說明]
網域 A (使用者端)
利用 jQuery AJAX 向網域 B 取得 JSON 格式的交換資料,並顯示出來。
網域 B (伺服器端)
提供公開數據,拋出 JSON 格式。PHP在設計的時候,需要判斷對方是否使用JSONP的方法來請求資料,如果是,就回應 JSONP 的方式,如果不是就使用純 JSON 格式輸出。
[程式碼模擬]
使用者端
1 2 3 4 5 6 7 8 9 10 11 12 13 14 |
$.ajax({ type: "GET", //使用JSONP務必在結尾使用 GET 的 callback=? url: 'http://cijsn.kiiuo.com/test/server.php?callback=?', dataType: "jsonp", data: { message: 'Helow World' }, success: function (data){ console.log(data) } }) |
伺服器端
1 2 3 4 5 6 7 8 9 10 11 12 13 14 |
<? // header 若指定 application/json,在同網域使用 $.get $.post 會自動解碼 // header("Content-type: application/json; charset=utf-8"); $data = json_encode(array("foo" => "bar")); //純json 格式 if (empty($_GET['callback'])) echo $data; //jsonp 方法 else echo "{$_GET['callback']}($data)"; |
PHP 主要就在這一段,如果對方網址沒有夾帶 $_GET[‘callback’] ,那麼就直接輸出 json
1 2 3 |
if (empty($_GET['callback'])) echo $data; |
相反的如果發現網址有夾帶 $_GET[‘callback’] ,那就必須回覆 JSONP的方法
1 2 3 |
else echo "{$_GET['callback']}($data)"; |
回覆 JSONP 的方法,就是
1 2 3 |
echo 對方指定夾帶的callback名稱(你的JSON字串); |
另外,若在 PHP 的部分沒有使用
1 2 3 |
header("Content-type: application/json; charset=utf-8"); |
那麼你可以在 jQuery AJAX success 的時候 console.log 發現
1 2 3 |
Resource interpreted as Script but transferred with MIME type text/html:傳送的網址 |
也就是說,因為我們在 PHP 沒有指定檔頭是什麼,PHP (我使用 Codeigniter ) 使用預設的 html 文檔輸出
1 2 3 |
header("Content-Type: text/html; charset=utf-8"); |
這對於 跨網域撈資料 的時候,比較沒什麼差別,因為 jQuery 使用 AJAX JSONP 取得 success callback 的時候,就會自動解碼 JSON 格式。所以當我們 console.log 可以發現已經是物件而不是字串了。
那麼差別在哪?
差別在 相同網域 的時候,因為沒有跨網域被禁止的問題,我們其實直接使用 $.post 或 $.get 的方法就可以了。
PHP 不指定header()為 application/json; 的話,$.post 在 callback 取得的是 JSON 字串
例如
1 2 3 4 5 6 7 8 9 10 11 |
$.post("同網域的網址", { message: 'Hello World' }, function (data){ //會發現取得的是 "字串" console.log(data) //所以要手動解碼 json var obj = JSON.parse(data); }) |