配列の値をWEBページに表示する方法

はじめに

Vue.jsではAjax通信でaxiosを使うのがスタンダードということで試してみたところ、axios公式のPOSTのExampleの通りに

JavaScript
axios.post('/user', {
    firstName: 'Fred',
    lastName: 'Flintstone'
  })
  .then(function (response) {
    console.log(response);
  })
  .catch(function (error) {
    console.log(error);
  });

で送信しても、PHPの $_POSTや$_REQUEST では値を受け取れません。これは、PHPがPOSTを Content-type: application/x-www-form-urlencoded のForm Dataの形式で受けるようになっているのに対し、Axiosのデフォルトでは Content-type: application/json でPayloadとして送信しているのが原因です。
参考: ブラウザの時にaxiosのPOSTの値が送信されない?そんなことはない
参考: backboneからのajaxがpayloadでPHPの$_POSTで取得できない

対策としては公式や上記の記事にあるように URLSearchParams を用いて application/x-www-form-urlencoded形式で送信する方法と、file_get_contents(‘php://input’) でapplication/json形式のPayloadを読みに行く方法などがあるようです。
参考: PHPでHTTP POSTされたJSON本文のbodyを受け取る方法

送信側で application/x-www-form-urlencoded に変換してもよいのですが、世の中の流れ的には application/json に傾きつつあるようですし、APIなどではどちらでも受け付けた方が親切だろうということで、受け側のPHPで両方に対応することを考えてみました。
使用したPHPのVersionは 7.1.11 です。

サンプルコード

まず最初に考えたのが以下のコードです。
目標は $request の中身が application/json の場合と application/x-www-form-urlencoded の場合で同じになることです。

PHP
$content_type = explode(';', trim(strtolower($_SERVER['CONTENT_TYPE'])));
$media_type = $content_type[0];

if ($_SERVER['REQUEST_METHOD'] == 'POST' && $media_type == 'application/json') {
    // application/json で送信されてきた場合の処理
    $request = json_decode(file_get_contents('php://input'), true);
} else {
    // application/x-www-form-urlencoded で送信されてきた場合の処理
    $request = $_REQUEST;
}

$_SERVER[‘CONTENT_TYPE’]に Content-type が ‘application/json; charset=utf-8’ のような形で入っているので、セミコロンの前までを切り出して $media_type に入れています。正規表現を用いた方がすっきりするかもしれません。$media_type が ‘application/json’ の場合は

$request = json_decode(file_get_contents('php://input'), true);

でPayloadの内容を読んで、連想配列にデコードします。

大抵の場合はこれで問題ないのですが、

JSON
{
    "id": 1,
    "name": {
        "first_name": "John",
        "last_name": "Doe"
    }
}

このような階層構造になったJSONデータをPOSTした場合、$_REQUEST[‘name’]の中身は連想配列ではなく {“first_name”: “John”,”last_name”: “Doe”} という文字列になるので、これを連想配列にデコードする必要があります。

PHP
$content_type = explode(';', trim(strtolower($_SERVER['CONTENT_TYPE'])));
$media_type = $content_type[0];

if ($_SERVER['REQUEST_METHOD'] == 'POST' && $media_type == 'application/json') {
    // application/json で送信されてきた場合の処理
    $request = json_decode(file_get_contents('php://input'), true);
} else {
    // application/x-www-form-urlencoded で送信されてきた場合の処理
    foreach ($_REQUEST as $key => $value) {
        $request[$key] = json_decode($value, true);

        // json_decodeはクォートされていない文字列がnullになるので戻す
        if ($request[$key] == null) {
            $request[$key] = $value;
        }
    }
}

$_REQUEST をforeachで回してjson_decodeすればOK・・・と思ったらjson_decode関数はクォートされていない文字列がnullになるという謎仕様らしいので、nullになったら元の値に戻すという処理を入れています。あまりスマートではありませんが・・・。

感想など

  • 今まであまりPOST時の Content-type やJSONデータの受け取り方を意識していなかったのでよい勉強になりました。でも将来的にはPHPの標準仕様で対応して欲しいですね。
  • ご意見やもっと良い方法があればコメントをよろしくお願いします。
[紹介元] PHPタグが付けられた新着投稿 – Qiita 配列の値をWEBページに表示する方法

  • コメント

    1. 匿名希望
      2018/01/22(月) 21:13:51

      JSの配列ソート、in-placeなのに戻り値にはソートされた配列が入るという謎仕様。気持ちがわからない

    2. 匿名希望
      2018/01/22(月) 21:13:51

      2次元の整数型配列aの各要素a(i,j)の値は,2i+jである。
      このとき,a(a(1,1)×2,a(2,2)+1)の値は幾つか。

      ア 12
      イ 13
      ウ 18
      エ 19

      【H28春6】

    3. 匿名希望
      2018/01/22(月) 21:13:51

      C値パラドックス:ゲノムサイズと生物の複雑さに明確な相関がないこと。反復配列の存在が原因ではないかと考えられている。

    4. 匿名希望
      2018/01/22(月) 21:13:51

      どなたか配列内の値を自由に入れ替えられる回路を教えてください(´・ω・`;)
      #Terraria

    5. 匿名希望
      2018/01/22(月) 21:13:51

      【配列で悩む時は】使えると思った配列やカレイドフェノムは無理して変更しなくともよい。イベントやフリー戦闘で入手できる同属性のオーパスをpec(稀少値)を高いのに変えればカレイドフェノムのランクも高くなり強力なのも使用できる。異なる属性だと配列をし直す必要も出てくるので注意。

    記事に戻る

関連記事