2015-01-13 84 views
1

我想從JavaScript發佈JSON數據到PHP。你可以做到這一點無論是爲什麼ajax`application/json`運行兩次PHP代碼?

Content-Type: application/json 

Content-Type: application/x-www-form-urlencoded 

這兩部作品,但我有一個很難得到的第一個工作。原因是我錯過了當內容類型爲application/json時,PHP腳本似乎運行了2次。

我很驚訝,不知道發生了什麼。任何人都可以解釋發生了什麼以及如何處理它? (有一些相關的問題,但沒有一個答案似乎觀察到這種行爲。)

這是我的測試代碼。首先啓動PHP內置服務器:

php.exe -S localhost:7000 

然後在該目錄下創建文件test1.php用下面的代碼:

<?php 
header("Access-Control-Allow-Origin: *"); 
header("Access-Control-Allow-Headers: Content-Type"); 
header("Content-Type: application/json"); 

function writeStdErr($msg) { $fh = fopen('php://stderr','a'); fwrite($fh, $msg); fclose($fh); } 
writeStdErr("\n\nI am here!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!\n"); 

$e = stripslashes(file_get_contents("php://input")); 
writeStdErr("e=".$e."\n"); 
if (strlen($e) > 0) echo $e; 
從Web瀏覽器控制檯

現在(我使用谷歌瀏覽器),從AJAX請求:

function test1(j) { 
    url = "http://localhost:7000/test1.php"; 

    type = "application/x-www-form-urlencoded"; 
    if (j) type = "application/json"; 

    xhr = new XMLHttpRequest(); 
    xhr.open("POST", url, true); 
    xhr.setRequestHeader("Content-type", type); 
    xhr.addEventListener("readystatechange", function() { 
     if (xhr.readyState == 4 && xhr.status == 200) { 
      var json = JSON.parse(xhr.responseText); 
      console.log(json.email + ", " + json.password) 
     } 
    }); 
    var data = JSON.stringify({"email":"[email protected]","type":type}); 
    xhr.send(data); 
    console.log("now sending >>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>", url, type); 
} 
test1(false) 

在控制檯輸出正是我所期待:

I am here!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! 
e={"email":"[email protected]","type":"application/x-www-form-urlencoded"} 

現在改爲使用applicaion/json進行ajax呼叫,即test1(true)。輸出結果如下:

I am here!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! 
e= 

I am here!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! 
e={"email":"[email protected]","type":"application/json"} 

正如你所看到的PHP代碼已經運行了兩次。並且第一次沒有輸入php://input

爲什麼?而這應該如何在PHP中處理?


借用這裏的一些代碼:Sending a JSON to server and retrieving a JSON in return, without JQuery

這裏有一些相關的問題: Code to be run twice in Ajax requestRunning curl twice in phphttps://stackoverflow.com/questions/24373623/ajax-request-help-code-gets-created-twiceAjax form submitting twice with Yii 2

而且這個問題(的投票這裏最高的國家之一)當然是相關的,但沒有什麼可以說爲什麼PHP代碼運行兩次:

What is the correct JSON content type?

回答

0

您的JavaScript代碼中有一些語法錯誤(如缺少括號)。你也應該使用「var」來聲明你的變量將範圍限制在函數中。也許這會導致這種奇怪的行爲。在更正javascript代碼後,我無法重現您提到的錯誤=>只有一個錯誤日誌條目,無論test1的參數設置爲true還是false。

以下是更正代碼 - 試試看:

function test1(j) { 
    var url = "http://localhost:7000/test1.php"; 
    var type = "application/x-www-form-urlencoded"; 

    if (j) { 
     type = "application/json"; 
    } 

    var xhr = new XMLHttpRequest(); 
    xhr.open("POST", url, true); 
    xhr.setRequestHeader("Content-type", type); 
    xhr.addEventListener("readystatechange", function() { 
      if (xhr.readyState == 4 && xhr.status == 200) { 
        var json = JSON.parse(xhr.responseText); 
        console.log(json.email + ", " + json.type) 
      } 
    }); 
    var data = JSON.stringify({"email":"[email protected]","type":type}); 
    xhr.send(data); 
    console.log("now sending >>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>", url, type); 
} 
test1(false); 

編輯:

啊,對不起我的壞。我沒有讀到您從JavaScript控制檯運行腳本。我將它嵌入到我通過瀏覽器調用的php文件中。所以這不是一個跨域請求,這就是它爲我工作的原因。

我現在能夠重現您的問題。正如您提供的鏈接所述,您應該檢查請求的HTTP方法是否爲「OPTIONS」請求=>如果是,只需返回標頭。

關於緩存問題:您可以通過「Access-Control-Max-Age」標題將預檢緩存時間設置爲零。

這裏是整個PHP代碼應該工作:

<?php 
    header("Access-Control-Allow-Origin: *"); 
    header("Access-Control-Allow-Headers: Content-Type"); 
    header("Content-Type: application/json"); 
    header("Access-Control-Max-Age: 0"); 

    if ($_SERVER['REQUEST_METHOD'] != 'OPTIONS') { 
     function writeStdErr($msg) { 
      $fh = fopen('php://stderr','a'); 
      fwrite($fh, $msg); 
      fclose($fh); 
     } 

     writeStdErr("\n\nI am here!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!\n"); 

     $e = stripslashes(file_get_contents("php://input")); 
     writeStdErr("e=".$e."\n"); 
     if (strlen($e) > 0) echo $e; 
    } 
?> 
+0

謝謝,但對我來說工作原理完全一樣。你使用的是什麼PHP?瀏覽器是什麼?(我的代碼實際上對你有不同的作用?) – Leo

+0

PHP 5.4.35,Firefox 33.1.1和LAMP。我也嘗試過使用內置的服務器 - 仍然無法重現。你是否與Firefox有同樣的行爲? – JanTheGun

+0

是的,我得到了與FF相同的行爲。在Windows 7上。 – Leo

0

我張貼這個答案,但誰解決了這個竟是羅馬Shtylman的人,請參閱預檢here今天他對CORS的意見(2015 - 01-13)。

的規則似乎沒有CORS飛行前,如果你使用application/x-www-form-urlencode,但如果你使用application/json

https://developer.mozilla.org/en-US/docs/Web/HTTP/Access_control_CORS

所以,往返可能是,如果使用「避免錯誤」的標題(即application/x-www-form-urlencode),這部分人則認爲:

https://remysharp.com/2011/04/21/getting-cors-working

但是......再有就是緩存:

http://www.html5rocks.com/en/tutorials/cors/

如果實際發生的緩存是另一個問題。我完全不知道這個問題的答案。 :-(