Vue.jsでSPAを作る際に、サーバーサイド側との通信とバッティングしないか気になっていた。
調べてみると、Vueで作った入力カ所をaxios(アクシオス)というライブライを用いてPHPと非同期通信を行うことが可能だということがわかった。
今回はこのaxiosライブラリを用いて、Vue.jsから入力フォームの値をPHPに送って結果を受け取るまでの処理を書いていく。
※今回のテストはローカル環境(XAMPP)で動くことを想定している。
Table of Contents
axiosとは?
axiosは固有のものではなく、JavaScriptで動作するブラウザやNode.jsのための非同期通信(HTTPリクエスト)を行うためのライブラリだ。
任意のAPIやサーバーと通信するためのツールとして使われるらしい。
Vue.js自体はフロントエンドのフレームワークであり、APIやサーバーとの通信の機能は持たないため、外部ライブラリ(この場合axios)を使用して非同期通信を行うことが一般的とされている。
axiosを使うためのVue(HTML側)のコード
まずはVue.jsを含んだHTML側のコードを書いていく。
詳しい内容はコメントアウトとして記載しているので、そちらを参考にしてもらいたい
<!DOCTYPE html>
<html lang="ja">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Vue.jsとPHP、Axiosを使った非同期通信テスト</title>
<script src="https://cdn.jsdelivr.net/npm/vue@2.6.14"></script>
<script src="https://cdn.jsdelivr.net/npm/axios@0.21.1/dist/axios.min.js"></script>
</head>
<body>
<div id="app">
<input v-model="email" placeholder="メールアドレス" value="aaa">
<!-- value="aaa"と設定しては、ユーザーが入力しても「email: 'aaa',」とは反映されず、空のままデータが送られてしまうので、vueではv-model=""を使用 -->
<input type="password" v-model="password" placeholder="パスワード">
<button @click="submitForm">送信</button>
</div>
<script>
new Vue({//インスタンス作成
el: '#app',//id要素指定
data() {//v-modelで指定した要素をデータに。ここではdata:{}のようなオブジェクトではなく関数で実行。
//コンポーネント再利用として再利用すつ必要がない場合(あるページに1つのVueインスタンスしかない場合)はdata:{}のようなオブジェクトで書いてオッケー。
//複数インスタンスがある場合はそのオブジェクトを各インスタンスが参照してしまうので、関数として書く。
return {//returnでVueインスタンスの初期値を決定しており、v-modelの双方向バインディングによって「email: '',」には入力した値がリアルタイムで入る。
//つまり双方にデータを返すためのお約束としてreturnは必要ということ
email: '',
password: ''
};
},
methods: {//処理内容
async submitForm() {//async は非同期関数を定義するキーワード。下でawait キーワードを使って、Promise(約束)を返す関数の完了を待つことができる。
try {//エラーが発生する可能性のあるコードのブロックをtry、erroerで実行
const response = await axios.post('register.php', { // 'await' を使って非同期関数の完了を待つ。axios.post は、引数として指定されたURL ('register.php') に POST リクエストを行う
email: this.email,//ユーザーが入力した内容(email: はオブジェクトのプロパティ名という意味)をPHPに送信
password: this.password//axiosを使用すると、オブジェクトはデフォルトでJSON形式に変換されて、HTTPリクエストのボディとして送信される
});//ここまでのPHPでの処理結果をresponseに格納
//await キーワードのおかげで、axios.post の結果が返ってくるまで処理が待たされ、その結果を次のif文で処理できる
if (response.data.success) {// // レスポンスのデータに 'success' プロパティが含まれているかどうかをチェックし、処理
//data:response オブジェクトのプロパティで、サーバーから返された実際のデータを含んでいる。PHPスクリプトによって生成されたJSONレスポンスを参照することになるという意味
//PHPで設定した「$data」 がエンコードされて送られてきた結果を受け取る
alert('登録成功!');
} else {
alert('エラー: ' + response.data.message);
}
} catch (error) {//例外が発生した場合
console.error('APIエラー:', error);
}
}
}
});
</script>
</body>
</html>
注目してもらいたいのは「const response = await axios.post(‘register.php’, {~~}」の部分だ。
axios.postで指定したphpファイルへ通信を行い、さらにawaitを使うことでその非同期通信が完了するのを待ってから次の処理(if文)へと処理を繋ぐことができるのだ。
axiosを使うためのPHP側のコード
ここからaxios経由のjsから受取ったデータをPHPで処理していく。
注意点としては、データはjson形式で送られてくるため、デコードして処理をし、その値を再びjsonにエンコードしてブラウザ側に返す必要があるのだ。
<?php
//※下記は通信を行うjs、phpが双方のファイルが「example.com(仮)」に置いてあれば、これらのheaderは不要だが、他のオリジン「test.com」から通信を行う場合は必須
header('Access-Control-Allow-Origin: *');//ブラウザ(オリジン)からのリクエストを許可するために使用。
//'*' はすべてのオリジンからのリクエストを許可することを意味しているが、「http://example.com」のような指定も可能
header('Access-Control-Allow-Methods: POST');// 許可されるHTTPメソッドを制御。この場合、POSTメソッドのみが許可される。
header('Content-Type: application/json; charset=UTF-8');// レスポンスのコンテンツタイプを設定(レスポンスはJSON形式で、文字エンコーディングはUTF-8)。
$data = json_decode(file_get_contents("php://input"));// "php://input"は非標準の入力ストリームとして、ブラウザからのPOSTリクエストなどで送信された生のデータを読み取ることができる。
// この例では、送信されたJSONデータをPHPのオブジェクトまたは配列に変換するために、json_decode()関数が使用されている。
if (isset($data->email) && isset($data->password)) {
// 実際のアプリケーションでDB登録や検証を行う処理をここに追加。
// 今回はデモとして常に成功を返すようにしている。
echo json_encode(['success' => true, 'message' => '登録完了']);// JavaScript側はJSON形式でデータを簡単に解析・利用できるため、APIやサーバーからのレスポンスとしてJSONを使用するのが一般的。
} else {
echo json_encode(['success' => false, 'message' => '無効なデータ']);
}
?>
今回はDB登録の処理は省いたが、フォームに値がセットされている場合は、通信が成功し、その結果を返すのみとなっている。
まとめ
axiosを使えばSPAでの開発が捗りそうだが、適応するページはその都度ユーザービリティを考慮しながら決めていく方がよさそうだ。