かもメモ

自分の落ちた落とし穴に何度も落ちる人のメモ帳

JavaScript (SPA) PHP axios でフォームデータを送る時に気をつけること

$_POSTfilter_input でデータを取得しているようなPHPのバックエンドにフォームデータを axios で送信する時 Content-Type を application/x-www-form-urlencoded にするだけでは上手くいきません。

🙅‍♀️ Content-Type: application/x-www-form-urlencoded でも上手く行かない例

バックエンド (PHP)

<?php
addRoute('POST', '/login', login);

function login() {
  $email = filter_input(INPUT_POST, 'email');
  $password = filter_input(INPUT_POST, 'password');
  // ログイン処理 
}

フロントのフォーム送信部分

const data = {
  email: 'example@example.com',
  password: 'password',
};
await axiso.post('/login', data, {
  headers: {
    'Content-Type': 'application/x-www-form-urlencoded',
  },
});

バックエンドで $email, $password が空文字列になるので上手く行かない。
この送り方だと $POST が次のような形になっている

<?php
function login() {
  var_dump($_POST);
  // => {{"email":"example2@example_com","password":"123456"}: ""}
}

🙆‍♀️ axios で フォームデータを送る時は URLSearchParams を使う

送信するデータを URLSearchParams の形式にする必要がある

const data = {
  email: 'example@example.com',
  password: 'password',
};

const params = new URLSearchParams();
Object.keys(data).forEach(function(key) {
  params.append(key, this[key]);
}, data);

await axiso.post('/login', params, {
  headers: {
    'Content-Type': 'application/x-www-form-urlencoded',
  },
});

👇
$_POST{email: "example2@example.com", password: "123456"} という形になるので、バックエンドの $_POSTfilter_input でフロントから送られたデータが正しく取得できるようになりました! ₍ ᐢ. ̫ .ᐢ ₎👌

公式のドキュメントには qs というパッケージを使う方法も載っていました。

import qs from 'qs';
const data = { 'bar': 123 };
const options = {
  method: 'POST',
  headers: { 'content-type': 'application/x-www-form-urlencoded' },
  data: qs.stringify(data),
  url,
};
axios(options);
cf. GitHub - axios/axios: Promise based HTTP client for the browser and node.js

所感

ちゃんとドキュメント読もうって事でした。
思い出せば、jQueryajax だと Object をそのまま送っても $_POST で取得できていた記憶があったので、jQuery 君、今までは君がいい感じに変換してくれてたんだね…って思ったのでした。


[参考]

北北西に曇と往け 1巻 (HARTA COMIX)

北北西に曇と往け 1巻 (HARTA COMIX)

アイスランド行きたい