PHP デコーディングしていると、$_POST
配列はとても便利なものですので、Web 開発では常用する変数になっています。PHP 4 とかの時代よりも、格段に実用的になっているので、すっかり頼り切ってしまいます。
今回のミッション
- JSON 送信を $_POST で受け取りたい!
$_POST
に POSTデータがない!
jQuery.ajax() で下の例のコード例で、サーバーに接続してみます。
js
// js
$.ajax({ // url はどこでもいいです。
url: 'http://192.168.1.5/data/phptest.php',
method: 'post',
data: JSON.stringify({a: 'x', b: 'y'}),
contentType: 'application/json'
});
これは、JSON として送信されます。
というのも、contentType が 'application/json'
となっているからです。
この JSON を受け取ったサーバー側で、$_POST
配列をダンプしてみます。
php コード例
// http://192.168.1.5/data/phptest.php
var_dump($_POST);
結果は、どうなるでしょうか。次のような結果になりました。
php
array(0) { }
$_POST
は空です。JSON で送ったデータ "{a: 'x', b: 'y'}"
がどこかに含まれていると期待していましたが、中身がみあたりません。
果たして {a: 'x', b: 'y'}
はどこに行ったのでしょうか?
$_POST
になぜデータが含まれないのか種明かし
調べるまでもないことなのかもしれませんが、知らなかったらハマるポイントです。
PHP が POST ペイロードを取り込んでくれるのは、"contentType" が "application/x-www-form-urlencoded" か "multipart/form-data
" の時に限ります。
私的には、知らなかったです。どこかで知っていたのかもしれませんが、意識していなかったのでハマりました(昔の話です)。
なぜ上の二つの場合にのみに限るのかといえば、実はたいした理由はありません。歴史的に、$_POST
が実装されたときにすでにあった "contentType" だけをサポートしているだけというのが理由のようです(理由になっていませんが)。他の "contentType については、自動的には読み込まないようになっているということです。
解決策とまとめ
とはいえ、"contentType" が人気の "application/json
" を無視するような PHP は使わないというわけにもいきません。次のように、リクエストの JSON データをデコードして(要するにコンテンツを手動解析して)、"$_POST
" 変数をオーバーライドすることで、普通に $_POST
から使えるようになります。
php
$_POST = json_decode(file_get_contents('php://input'), true);
確認のため、$_POST
配列をダンプしてみると、配列にしっかり正しく含まれています。
php
array(2) { ["a"]=> string(1) "x" ["b"]=> string(1) "y" }
今回のミッションは終了です。