表題の件を実装することになったのですが、途中クロスオリジン関係で嵌まったのでメモしておきます。
前提
今回の前提としては下記のような状態です。
- フロントエンド: Vue.js + axios
- バックエンド: PHP (dietcake)
- 開発用PC上でPHPもVue.jsも動作
- PHPは普通に
https://localhost/hoge/piyo
のようなURL - Vue.jsは
npm run serve
の開発環境なのでhttp://localhost:8080
- ここでポート番号が異なるのでクロスオリジンに引っかかる
最初のコード
最初は
axiosのドキュメントにあるサンプルのやり方で試してみました。
Form.vue(JavaScript)
const APIURL = 'http://localhost/app/webroot/'
axios.post(APIURL + 'hoge/piyo', this.senddata)
.then(function (response) {
console.log(response)
})
.catch(function (error) {
console.log(error)
})
PHP(hoge/piyo.php)
<?php
if(!ENV_PRODUCTION) {
header('Access-Control-Allow-Origin: *');
}
$jsonString = file_get_contents('php://input');
file_put_contents("json.json", $jsonString);
exit();
こんな感じ(dietcakeなのでcontrollerとかも記述していますが、ここでは関係ないので省いています)でpost。
すると、
Access to XMLHttpRequest at ‘http://localhost/app/webroot/hoge/piyo’ from origin ‘http://localhost:8080’ has been blocked by CORS policy: Request header field access-control-allow-origin is not allowed by Access-Control-Allow-Headers in preflight response.
と怒られました。
修正コード(途中)
色々試行錯誤した結果、以下のように修正。
Form.vue(JavaScript)
const APIURL = 'http://localhost/app/webroot/'
const axiosApi = axios.create({
headers: {
'Content-Type':'application/json'
}
})
axiosApi.post(APIURL + 'hoge/piyo', JSON.stringify(this.senddata))
.then((response) => {
console.log(response)
})
.catch((error) => {
console.log(error)
})
PHP(hoge/piyo.php)
<?php
if(!ENV_PRODUCTION) {
header('Access-Control-Allow-Origin: http://localhost:8080');
}
header('Access-Control-Allow-Headers: Content-Type');
$jsonString = file_get_contents('php://input');
file_put_contents("json.json", $jsonString);
exit();
主な変更点は以下の通り
- axios側
- axiosは予め設定を固定化するために
axios.create()
でheaders
にContent-type: application/json
を指定 - jsonデータを
JSON.stringfy
で文字列化
- PHP側
Access-Control-Allow-Origin
をワイルドカードではなくキチンと指定Access-Control-Allow-Headers
指定を追加
これで送信できるようになり、中身にデータが入ったjsonファイルが生成されることを確認しました。
修正コード(最終)
さて、上記のコードを見て分かる方は分かると思うのですが
- axiosでpostする際のデフォルトのヘッダは
Content-type: application/json
- axiosのサンプルコードではjsonをそのままpostに含んでいた
ので、「実はJS側の修正はいらなかったのではないか?」という疑問が。そこでJSだけを元に戻してみます。
Form.vue(JavaScript)
const APIURL = 'http://localhost/app/webroot/'
axios.post(APIURL + 'hoge/piyo', this.senddata)
.then(function (response) {
console.log(response)
})
.catch(function (error) {
console.log(error)
})
PHP(hoge/piyo.php)
<?php
if(!ENV_PRODUCTION) {
header('Access-Control-Allow-Origin: http://localhost:8080');
}
header('Access-Control-Allow-Headers: Content-Type');
$jsonString = file_get_contents('php://input');
file_put_contents("json.json", $jsonString);
exit();
これでも成功しました……。
ということで、結果的にはPHP側の修正だけで良かった、ということになりました。
余談
PHPでjsonを受け取る際は
file_get_contents('php://input');
が一番楽そうだと感じました。
参考
axios
PHPでjsonを受け取る
その他参考