PHP Manual
/
HTTP

PHPでAjaxのPOSTリクエストを処理する

01. 11. 2019

Obsah článku

Vue.jsのajaxアプリケーションを開発する中で、何年か経ってようやくPHPでajaxを使う方法、POSTメソッドでデータを受け取る方法がわかりました。

スーパーグローバル変数 $_POST はフォームに対してのみ有効です。

PHP では、フォームから送信されたデータを保持するために superglobal variable $_POST が一般的に利用可能です。

使い方は比較的簡単です。

HTML側では、フォームを作成する必要があります。

<form action="process.php" method="post">
Jméno: <input type="text" name="username">
<input type="submit" value="Odeslat">
</form>

そして、process.php ファイルでその値を配列の要素としてアクセスできるようにします。

echo htmlspecialchars($_POST['ユーザー名'] ?? '');

警告:

この単純なアプローチでは、誰もが POST されたデータは自動的に $_POST 変数の配列インデックスとして定義されていると感じるかもしれません。しかし、そんなことはありません。

実際、POST メソッドを使ってフォームから送られたデータが $_POST 変数に書き込まれるのは、HTML フォームが送信されたときにブラウザが自動的に HTTP ヘッダー 'Content-Type': 'application/x-www-form-urlencoded' を送信するためです。

ヘッダーが適切に設定されていないと、単純に値にアクセスすることができないため、トリック・ソリューションを使用する必要があるのです。

ajaxでデータを送信する

ajaxを使ってデータを送ろうとする場合、PHP側で少しアプローチを変える必要があります。詳しくは、Facebookでの議論をご覧ください。

javascriptでは、例えばaxiosというライブラリを使うと、ajaxを使ってデータを送信することができます。簡単に使うには、CDNサーバーからjavascriptをリンクして、そのまま使うだけです。

<script src="https://unpkg.com/axios/dist/axios.min.js"></script>
<script>
axios.post('/api/form-process', {
username: 'Jméno uživatele'
})
.then(response => {
// Zpracování odpovědi z API
alert(response.data.message); // Vyhodí hlášku se zprávou
});
</script>

この単純なケースでは、URL '/api/form-process' が ajax で呼び出され、POST メソッドはオブジェクト { username: 'User name' } を渡します。データを渡すための物流はすでにライブラリ自身が自動的に処理しているので、Jsonとしてシリアライズして送られます。フロントエンド開発者の用語では、これを json payload と呼びます。

PHP側では、フォームとして使うことを想定しています(なにしろ、POSTメソッドですから)。

echo htmlspecialchars($_POST['ユーザー名'] ?? '');

ただし、この場合 $_POST フィールドは空となり、データは渡されません。変数 $_POST はフォームから取得したデータにのみ使用されます (捨てなかった HTTP ヘッダーを見ればわかります)。

そこで今回は、HTTPリクエストから直接データを取得する必要があり、そのためにトリック・ソリューションが使用されています。すると、使い勝手がよくなります。

$data = json_decode(file_get_contents('php://input'), true);
echo htmlspecialchars($data['ユーザー名'] ?? '');
header('Content-Type: application/json');
echo json_encode([
'メッセージ' => 'サーバー・クリーパー',
]);
die;

例として、簡単なjavascriptでの回答も用意しています。重要なのは、HTTPヘッダ 'Content-Type: application/json' を適切に投げ、すべてのデータが送信された後にスクリプトを終了させることです。

$_POST` の使用を強制する。

それでも投稿されたデータをそのままフォームとして扱いたい場合は、転送する方法があります。この場合、ajaxクエリの作成自体を修正し、HTTPヘッダを正しく渡す必要があります。

axios.post(
'/api/form-process',
{
username: 'Jméno uživatele'
},
{
headers: {'Content-Type': 'application/x-www-form-urlencoded'}
}
).then(response => {
// Nějaké zpracování
});

しかし、この場合、データを修正して配列に変換する必要があるため、PHP側の処理は快適ではありません。

なんとかこのホラーを思いつきました。

if (\count($_POST) === 1
&& preg_match('/^\{.*\}$/', $post = array_keys($_POST)[0])
&& ($json = json_decode($post)) instanceof \stdClass
) {
foreach ($json as $key => $value) {
$_POST[$key] = $value;
unset($_POST[$post]);
}
}
echo htmlspecialchars($_POST['ユーザー名'] ?? '');

しかし、最初の方法にこだわって 'php://input' メソッドを使用してデータを取得する方がずっとよいでしょう。

Jan Barášek   Více o autorovi

Autor článku pracuje jako seniorní vývojář a software architekt v Praze. Navrhuje a spravuje velké webové aplikace, které znáte a používáte. Od roku 2009 nabral bohaté zkušenosti, které tímto webem předává dál.

Rád vám pomůžu:

Související články

1.
4.
Status:
All systems normal.
2024