【javascript】Ajaxの使い方とは?phpのPOSTへの受け渡し方とコードを徹底解説!
この記事からわかること
- Ajaxとは?
- Ajaxの使い方
- javascriptでのコードの書き方と意味
index
[open]
\ アプリをリリースしました /
友達や家族の誕生日をメモ!通知も届く-みんなの誕生日-
posted withアプリーチ
webページを作成するに当たってページをいちいちリロードしていては処理が遅くなりますし、ユーザーからしてもストレスになってしまいます。
ajaxという機能を使えばページの一部分だけを更新することができるのでページ自体をリロードする必要がなく、よりユーザーが使いやすいwebページを作ることができます。
ajaxとはどのようなものでどんなふうにコードを書いて使うのかをまとめていきたいと思います。
Ajax(エイジャックス)とは
Ajax(エイジャックス/アジャックス)とは「Asynchronous JavaScript And XML」の略称でjavascriptを使ってwebページの一部分を更新する仕組みのことです。
Asynchronous(アシンクロナス)とは日本語で「非同期」という意味です。同期処理がタイミングを合わせて処理を行うことを指すので、非同期処理はその逆、タイミングを合わせずに別々に処理を行えることを指します。
ここでいう非同期はサーバー側とクライアント側(ユーザー)の処理を別々に行えるということ 。それによりページ全体をリロード(全てのタイミングを合わせて処理)しなくてもページの一部分だけが更新(更新したい部分だけ非同期で処理)できるようになります。
Ajaxのメリット
- 一部分だけ更新するので画面のチラつきが起きにくい
- 通信量も最低限で済む
- 動的な更新が可能
javascriptでのAjaxの使い方
Ajaxを実装するためのコードはこのようになります。
document.addEventListener('DOMContentLoaded', function() {
setInterval(startAjax, 1000);
function startAjax() {
let xhr = new XMLHttpRequest();
// 非同期通信を試みる
xhr.open('GET', 'index.php?name=' + "デザイン太郎", true);
xhr.send(null);
// 非同期通信の結果を確認
xhr.onreadystatechange = function() {
if (xhr.readyState === 4) { // #1
// #1 非同期通信が完了した後の処理
if (xhr.status === 200) { // #2
// #2 非同期通信が成功した後の処理
}else{ // #2
// #2 非同期通信が失敗した後の処理
} // #2
} else { // #1
// #1 非同期通信が完了する前の処理
} // #1
}
}
}, false);
Ajaxで重要となってくるのがXMLHttpRequestオブジェクトです。
XMLHttpRequestオブジェクトはサーバー側と通信するための処理を行うことができるオブジェクトです。
XML形式のファイルだけに特化したわけではなく、それ以外のデータ形式であっても取得することができます。
Ajaxのコードの流れ
- webページ(コンテンツ)を読み込む
- Ajaxを発火するタイミングを指定
- XMLHttpRequestオブジェクトをインスタンス化(生成)
- 非同期リクエストを構築→送信
- サーバーとの通信結果の分岐を記述
Ajaxを発火させるタイミングを指定
1〜5行目
まず1番最初にwebページのコンテンツが全て読み込み終わるタイミングでコードを実行させるようにします。これはいつもの流れですね!
document.addEventListener('DOMContentLoaded', function() {
今回はAjaxを起動させるタイミングをsetIntervalメソッドでコントロールしています。setInterval
は第1引数に指定したコード(今回は関数)を、第2引数に指定したミリ秒数ごとに実行するメソッドです。
setInterval(startAjax, 1000);
// 1秒(1000ミリ秒)ごとにstartAjaxを実行する
Ajaxの実装コードは関数(今回はstartAjax
)にしてまとめておきます。これで関数を呼び出すだけでAjaxが実行されます。
発火させるタイミングは何でも良いので自由できます。クリック時やスクロール時など通常のjavascriptのようにイベントを指定すると使いやすいです。
ここからがAjaxに関わるコードになっていきます。
XMLHttpRequestオブジェクトでAjax操作
6行目
let xhr = new XMLHttpRequest();
まずはXMLHttpRequestオブジェクト
をインスタンス化して変数に格納します。これでこの変数からサーバーにデータを送信したり、XMLHttpRequestに関わるイベントの変化を取得することができるようになります。つまりサーバーとの接続状況を変更/取得できるようになるということです。
8行目
xhr.open('GET', 'index.php?name=' + "デザイン太郎", true);
このコードで非同期通信するための準備をします。ここでいう準備とはリクエストを作成(初期化)することです。
そもそもwebページはクライアント(ユーザー)からのリクエストに対してサーバーからレスポンスを返すことでページを表示しています。そのリクエストの部分をここで初期化して設定しなおしているのです。
XMLHttpRequest.open(method, url[, async[, user[, password]]])
- method:HTTPリクエストメソッド('POST'や'GET'など)
- url:ajax通信させたいURL(パス)
- async:操作を非同期で行うかどうか(true or false)
- user/password:認証プロセスがある場合に記述
今回のコードはリクエストメソッドは「GET」でURLは「index.php」、GETの値としてキー値「name」の中に「デザイン太郎」を格納しています。
9行目
xhr.send(null);
この行で実際に準備したリクエストを送信しています。
GETの場合は引数に指定した文字は無視されるのでnull
を入れ込んでおきます。POSTの場合はここに値を入れ込むことで受け渡しが可能になります。POSTの送信方法は後述します。
非同期通信の可否で分岐処理
ここからは送信したリクエストによって返ってきたレスポンスの結果によって分岐処理をしていきます。
12行目
xhr.onreadystatechange = function () {
onreadystatechangeプロパティ
は後から解説するreadyState属性
の値が変化するたびに呼び出され、右側に記述したコードを実行します。ここに無名関数でajaxの通信結果の処理を記述していきます。
8行目
readyState
属性は非同期の通信の状態を確認できます。なのでここでは大前提に非同期の通信が完了したかどうかで分岐できるようにしています。
if (xhr.readyState === 4) { // #1
// #1 非同期通信が完了した後の処理
} else { // #1
// #1 非同期通信が完了する前の処理
} // #1
readyState属性
の戻り値は以下の通りです。
readyState属性の値と意味
戻り値 | 意味 |
---|---|
0 | openメソッドが呼び出される前 |
1 | openメソッドが呼び出されたが、sendメソッドは呼び出されていない時 |
2 | open/sendメソッドが呼び出されたが、応答ステータス/ヘッダーは未取得 |
3 | 応答ステータス/ヘッダーを取得したが、本文は未取得 |
4 | 全てのデータを取得 |
非同期通信が成功したかどうかをジャッジするのはこの次の処理です。流れとしてはまず通信が完了したかどうか。その後にその完了した通信は成功したかどうかを確認します。
16〜20行目
if (xhr.status === 200) { // #2
// #2 非同期通信が成功した後の処理
}else{ // #2
// #2 非同期通信が失敗した後の処理
} // #2
ここで「HTTPステータス」の値(サーバーでの処理結果)を確認することでAjax通信が成功したかどうかを判断しています。判断するのはstatus属性
の役割です。
status属性はデベロッパーツールで値を確認することもできます。使い方はこちらの記事にまとめてありますのでご覧ください。
HTTPステータスの値と意味
HTTPステータスの値 | 意味 |
---|---|
200 | 成功 |
302 | リダイレクト |
401 | 認証が必要 |
404 | リソースが見つからない |
500 | サーバーエラー |
Ajaxで送信したリクエストのレスポンスがHTTPステータス200(=成功)を返した場合のみ処理を行わせます。
これでAjaxの使い方の流れは終了しました。しかしここではまだ非同期通信をしただけなので実際に使えるパターンをまとめていきます。
Ajaxを使って文字を表示させる方法
例えばAjaxを使って動的にページの本文を変化させる方法です。
Ajaxの挙動を分かりやすくするためにまずphpファイルを2つ、jsファイルを1つ用意します。
構成ファイル
- index.html
- ajax.php
- main.js
Ajaxを使ったテキスト更新プログラム
まずは基礎となるHTMLファイルを作成します。form要素
のmethod属性
はあえて何も指定しないでおきます。これでこのHTMLファイルからformのデータがGETやPOSTへ渡ることは無くなりました。
<!DOCTYPE html>
<html lang="ja">
<head>
<meta charset="utf-8">
<title>ajax</title>
</head>
<body method="post">
<p id="result">ここの本文をAjaxでテキストエリアに入力された値に入れ替えます。</p>
<form>
<textarea id="text" type="text" name="text" ></textarea>
<input id="btn" type="button" name="submit" value="本文を変更" style="display:block">
</form>
<script src="ajax.js"></script>
</body>
</html>
次にphpファイルを作成します。中身は$_POSTに値が入っている場合のみその値をページ上に表示させるだけです。
この段階ではHTMLファイルとphpファイルはリンクされていません。
<?php
if(isset($_POST['text'])){
print $_POST['text'];
}
2つのファイルをリンクづける役割を今回はjsファイルに託します。ajaxを使って動的に本文を変更させる処理を記述していきます。
document.addEventListener('DOMContentLoaded', function() {
document.getElementById('btn').addEventListener('click', function() {
if (document.getElementById('text').value !== "") {
let result = document.getElementById('result');
let xhr = new XMLHttpRequest();
xhr.open('POST', 'ajax.php', true);
xhr.setRequestHeader("Content-Type", "application/x-www-form-urlencoded;charset=UTF-8");
xhr.send('text=' + encodeURIComponent(document.getElementById('text').value));
xhr.onreadystatechange = function() {
if (xhr.readyState === 4) {
if (xhr.status === 200) {
result.textContent = xhr.responseText;
}
};
}
}
}, false);
}, false);
2行目
まず発火のタイミングはid='btn'
が押されたタイミングに指定します。
4行目
その後にtextareaの中身が空の場合は処理を終了、値があれば非同期処理へと移っていきます。
ajaxを使ったPOSTでの通信方法
9〜11行目
xhr.open('POST', 'ajax.php', true);
xhr.setRequestHeader("Content-Type", "application/x-www-form-urlencoded;charset=UTF-8");
xhr.send('text=' + encodeURIComponent(document.getElementById('text').value));
AjaxでのGETでのリクエストの送信方法は先ほど説明しましたがPOSTの場合だとコードが少し異なってきます。
まずopenメソッド
のmethodには「POST」を指定します。URLはGETのように「?=""」で値を渡すことができないのでファイル名のみ(相対パス)を記述しておきます。
POSTを使う時はsetRequestHeaderメソッド
を使用してHTTPリクエストヘッダーの値を設定します。このコードが抜けていると正しく動作しないことがあるので要注意です。
POSTの値を受け渡す方法はsendメソッド
で記述します。GETの時はnull値
を指定していた引数に「キー値=データ」の形式で指定すればOKです。
今回は入力値をそのまま反映させるのでencodeURIComponent関数
を使ってエンコードしておきます。
encodeURIComponent関数は「 ; , / ? : + 」などの特殊文字をエスケープシーケンスに置き換えてくれる関数です。
これで値をPOSTで送信することができました。送信先は「ajax.php」です。
Ajaxで取得した値の適用方法
通信のくだりは先ほど説明したままです。そして今回は通信が成功した時に処理を1つ行っています。
result.textContent = xhr.responseText;
ここでは本文を表示するresult
のテキスト部分を司るtextContentプロパティ
に値を入れ込んでいます。
入れ込む値はxhr.responseText
で取得したajax.phpに表示されているテキストデータです。
現在のajax.phpをPOSTにデータがある状態で表示させると入力した値だけが表示されているページになります。responseTextは非同期通信をしたファイルを開いたページに表示されているテキストデータを全て取得し返します。
なのでもしajax.phpがこのようにいらないテキストデータを表示させているとそのデータも一緒に表示されてしまうので注意してください。
<?php
if(isset($_POST['text'])){
print $_POST['text'];
// exit(); ⇦ココにexit関数を入れれば不要なテキストがあっても表示されない
}
print '不要なテキスト';
もしこのajax.phpファイルに他のphpでの記述がしてあればexit関数
でスクリプトを強制終了させれば終了以前のテキストデータしか表示されなくなります。
この方法を使えばわざわざajax.phpを作らなくてもindex.phpとjsファイルだけで良くなります。index.htmlではなくindex.phpです。
最初のindex.htmlの拡張子を.phpに変更し<!DOCTYPE html>の上部にajax.phpに記述していたコードを記述します。
<?php
if(isset($_POST['text'])){
print $_POST['text'];
exit();
}
?>
<!DOCTYPE html>
<html lang="ja">
あとはjsファイルの9行目のこの部分のファイル名を「index.php」に変更すればOKです。これでファイルを増やすことなくajaxを実装できます。
xhr.open('POST', 'index.php', true);
Ajaxで挿入するデータをHTMLの要素にする方法
result.textContent = xhr.responseText; // 16行目
この方法だとプレーンなテキストデータしか挿入できません。例えば以下のような、入力値をHTMLのh2タグ
で囲ったデータを追加しようとしてもHTMLタグとしてではなく、ただの文字列として挿入されてしまいます。
<?php
if(isset($_POST['text'])){
echo "<h2>".$_POST['text']."</h2>";
exit();
}
?>
そのような場合は以下のコードで解決できます。
result.insertAdjacentHTML('beforebegin', xhr.responseText);
insertAdjacentHTMLメソッド
は第1引数に指定した場所に第2引数に指定したエレメント(HTMLタグ)を挿入するメソッドです。
insertAdjacentHTMLメソッドの第1引数
<!-- beforebegin --> ⇦ ココに<h2>入力値</h2>が追加される
<p id="result">
<!-- afterbegin -->
テキスト
<!-- beforeend -->
</p>
<!-- afterend -->
この方法ではHTMLタグを1つ新たに追加しているのでテキストの部分を削除しないといけません。削除するにはresult.textContent
に空文字を入ればOKです。
result.textContent = '';
result.insertAdjacentHTML('beforebegin', xhr.responseText);
最後に
これでJavaScriptでのAjaxの実装は完了です。今回は生のコードを使って記述しましたがライブラリなどを使えばもっと簡単に実装もできるようです。またJQueryでのAjaxも実装できるようなのでいつかチャレンジしてみたいと思います。
まだまだ勉強中ですので間違っている点や至らぬ点がありましたら教えていただけると助かります。
ご覧いただきありがとうございました。