axiosでPHPへPOSTしたデータを$_POSTを取得できない

ajax通信でPHPへデータを送信する際に$_POSTで値を受け取れない問題について、お話しようと思います。
最近、ReactとPHPを組み合わせたWebアプリケーション開発で、axiosを使ってPOSTリクエストを送信したところ、PHP側で$_POSTが空の配列になってしまうという問題に遭遇しました。FormDataを使えば問題なく動作するのに、普通にオブジェクトを送信すると$_POSTで受け取れない。この現象について調査し、Content-Typeの違いが原因であることがわかりました。同じような問題で悩んでいる方も多いと思いますので、この問題の原因と解決方法について詳しくまとめてみました。

なぜ$_POSTで値を受け取れないのか

axiosやfetchを使用したajax通信では、デフォルトでJSONデータを送信することが多く、この場合PHPの$_POSTスーパーグローバル変数では値を取得できないです。
これは、PHPが$_POSTに値を格納する条件が限定的であるためです。

$_POSTに値が格納される条件

PHPが$_POSTに値を自動的に格納するのは、以下の条件を満たす場合のみです。

  • Content-Typeがapplication/x-www-form-urlencodedの場合
  • Content-Typeがmultipart/form-dataの場合

これ以外のContent-Type(特にapplication/json)では、$_POSTは空の配列になります。

問題が発生する具体例

// JavaScript側
axios.post('/api/endpoint.php', {
    name: '田中太郎',
    email: '[email protected]'
})
.then(response => console.log(response.data));

// api/endpoint.php
var_dump($_POST); // array(0) { } 空の配列

この場合、axiosはデフォルトでContent-Typeをapplication/jsonとして送信するため、$_POSTでは受け取れません。

解決方法

方法1: PHP側でJSONを直接受け取る

// PHP側でJSONデータを受け取る
$json = file_get_contents('php://input');
$data = json_decode($json, true);

echo $data['name'];  // 田中太郎
echo $data['email']; // [email protected]

方法2: FormDataを使用する(JavaScript側の修正)

// JavaScript側 - FormDataを使用
const formData = new FormData();
formData.append('name', '田中太郎');
formData.append('email', '[email protected]');

axios.post('/api/endpoint.php', formData)
    .then(response => console.log(response.data));

方法3: URLSearchParamsを使用する(JavaScript側の修正)

// JavaScript側 - URLSearchParamsを使用
const params = new URLSearchParams();
params.append('name', '田中太郎');
params.append('email', '[email protected]');

axios.post('/api/endpoint.php', params)
    .then(response => console.log(response.data));

方法4: Content-Typeを明示的に指定する

// JavaScript側 - axiosの場合
axios.post('/api/endpoint.php', 
    'name=田中太郎[email protected]',
    {
        headers: {
            'Content-Type': 'application/x-www-form-urlencoded'
        }
    }
)
.then(response => console.log(response.data));

// fetchの場合
fetch('/api/endpoint.php', {
    method: 'POST',
    headers: {
        'Content-Type': 'application/x-www-form-urlencoded'
    },
    body: 'name=田中太郎[email protected]'
})
.then(response => response.json())
.then(data => console.log(data));

まとめ

ajax通信で$_POSTが空になる問題は、Content-Typeの違いが原因でした。
JSONデータを送信する場合はphp://inputから直接取得するか、JavaScript側でFormDataやURLSearchParamsを使用することで解決が可能です。

プロジェクトの要件に応じた実装方法で選択して、セキュリティ対策も忘れずに実装することが重要だなと思います。

この記事を気に入ったら

柄本 広樹

美しい景色、人、食べ物、そんな当たり前の日常に彩るすべてに感謝し、 今も映像を作り続ける。

この人が書いた記事を見る >>