ajax通信でPHPへデータを送信する際に$_POSTで値を受け取れない問題について、お話しようと思います。
最近、ReactとPHPを組み合わせたWebアプリケーション開発で、axiosを使ってPOSTリクエストを送信したところ、PHP側で$_POSTが空の配列になってしまうという問題に遭遇しました。FormDataを使えば問題なく動作するのに、普通にオブジェクトを送信すると$_POSTで受け取れない。この現象について調査し、Content-Typeの違いが原因であることがわかりました。同じような問題で悩んでいる方も多いと思いますので、この問題の原因と解決方法について詳しくまとめてみました。
INDEX
なぜ$_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を使用することで解決が可能です。
プロジェクトの要件に応じた実装方法で選択して、セキュリティ対策も忘れずに実装することが重要だなと思います。