JSON POST

コード

[PHP]うっかりミス $_POST に JSON POSTデータがない!

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" }

今回のミッションは終了です。

-コード
-, , ,

© 2020 ネーテルス