backboneからのajaxがpayloadでPHPの$_POSTで取得できない
なんか何言ってるかよくわからないタイトルになっちゃいました。
状況としては、BackboneからサーバーにBackbone::synsを通じてPOST→通常のajaxと同じようにサーバー側(PHP)の$_POST
で取得しようとすると値が空。
chromeのdevelper toolのnetworkタブで送信内容を確認すると普段はFormData
となっているところが
送信されるものがpayload
となっていました。どうやらこれが原因のようです。
payloadとは?
payloadとは一般的にhttpリクエストのhttpヘッダーを除いたボディ部分のようです。つまり送信内容そのものということでしょうか。
FormDataとpayloadの違い
どちらもブラウザからデータを送ってることは同じですがContent-Type
とそれに伴いサーバーからのデータの見え方が違うようです。
// FormData Content-Type: application/x-www-form-urlencoded foo=bar&name=John // payload Content-Type: application/json { "foo" : "bar", "name" : "John" }
つまりContent-Type
をapplication/x-www-form-urlencoded
で送信したものはFormData
として送信され、application/json
で送信したものはpayload
として送信されます。
application/json
はjsonを返す際にかならず設定するコンテンツタイプですね。サーバーからの見え方もJSONそのものです。
http - What's the difference between "Request Payload" vs "Form Data" as seen in Chrome dev tools Network tab - Stack Overflow
payload
を使うとJSONを送信するので、文字列以外にもオブジェクトやブール値など多様なデータを送信できるという利点があります。
違いはわかったので肝心の取得する方法です。やり方は2つあります。
1.サーバー側(PHP)でpayloadを取り扱う方法
$_POST
のかわりに以下の方法で取得できます。
$request_body = file_get_contents('php://input'); $data = json_decode($request_body);
How to retrieve Request Payload
え?php:// inputって?
PHPのマニュアルによると
php://input
は読み込み専用のストリームで、 リクエストの body 部から生のデータを読み込むことができます。
PHP: php:// - Manual
つまりサーバーにリクエストとして送ったデータそのものを取得できるようです。イマイチ$_POST
ととの違いがわかりませんよね。
ところでどうしてpayload
で送信されたデータを$_POST
を介して取得出来ないかというと答えはマニュアルに書いてありました。
Content-Type に application/x-www-form-urlencoded あるいは multipart/form-data を用いた HTTP リクエストで、 HTTP POST メソッドから現在のスクリプトに渡された変数の連想配列です。
PHP: $_POST - Manual
「どうしてpayloadの送信を$_POSTで取得できないか?」と言うよりそもそも$_POST
の定義としてpayload
をカバーしていないということです。マニュアル読むの大事ですね。
さらに調べてみると、application/x-www-form-urlencoded
とmultipart/form-data-encoded
の2つはブラウザが必ずサポートしなければならないコンテンツタイプなのでPHPでもこれらにアクセスするためのラッパーとして$_POST
を用意しているようです。
ajax - PHP "php://input" vs $_POST - Stack Overflow
2.クライアントからFormDataとして送信する方法
いつもどおり$_POST
を介して取得するにはコンテンツタイプをapplication/x-www-form-urlencoded
にして送信すればOKでこれはBackboneでは以下の用にして設定できます。
Backbone.emulateJSON = true
ちなみにangularの場合はこちらで紹介されています。
angularJSの$httpで送ったデータを$_POSTで受け取る - Qiita
以上です。
何か誤りを見つけられましたらご指摘いただけると大変ありがたいです!コメント欄でも@egapoolでも。