【PHP】Ajaxを使用して、フォーム検索時にワード候補を表示する

#Ajaxとは
Ajax = Asynchronous JavaScript + XML の略。
まず理解しておくことはAjaxは言語でもライブラリでもフレームワークでもなく、**JavaScriptとXMLを使って非同期でWebサーバと通信を行う**ことであり、Web上のUIを構築手法であること。

# サンプルコード

キーを入力するごとに名前を取得して候補を表示させる検索ボックスです。
仕組みをプログラムを書いただけですので、下の動画ではPHPの配列にあらかじめ格納した平仮名の名前を表示させています。

実務や本格的なサービスではデータベースやAPIからデータを取得することが多いと思います。

![画面収録-2020-10-24-18.00.53.gif](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/496595/ea9a06bd-d59a-844f-5264-6c31575798a9.gif)

```index.html
<!DOCTYPE html>
<html lang="ja">
<head>
  <meta charset="UTF-8">
  <meta name="viewport" content="width=device-width, initial-scale=1.0">
  <title>Ajaxで絞り込み検索機能</title>
  <script src="https://ajax.googleapis.com/ajax/libs/jquery/3.4.1/jquery.min.js"></script>
  <script>
    $(document).ready(function(){
      //ajax
      function keyword(){
        var name_input = $("#name").val();
        var data = {
          name: name_input
        }
        $.ajax({
          url: "/search.php",
          type: "POST",
          data: data,
          timespan: 5000
        }).done(function (data) {
          //入力されるたびに、候補ボックスをリセットする(ajaxから値が帰ってきたときだけ)
          $("#result").empty();
          // JSONを読み込む（リストを取得する）
          var search_word = JSON.parse(data || "null");
          // 入力ワードがあれば
          if (search_word.length != 0){
            for (var i = 0; i < search_word.length; i++) {
              // 一致しているデータだけ表示させる
              $('<li>').text(search_word[i]).prependTo('#result');
            }
          }else{
            $('#result').text("一致する名前は存在しません");
          }
        }).fail(function () {
        });
      }
      $("#name").keyup(function(){
        keyword();
      });
    });
    </script>
</head>
<body>
  <!-- 入力ボックス -->
  <input type="text" id="name">
  <!-- 絞り込み結果を表示 -->
  <ul id="result"></ul>
</body>
</html>
```

```search.php
<?php
  //ajaxリクエスト判定
  if(isset($_SERVER['HTTP_X_REQUESTED_WITH']) && strtolower($_SERVER['HTTP_X_REQUESTED_WITH']) == 'xmlhttprequest'){
    //ajaxからデータが送られてきた場合
    if(isset($_POST['name'])){
	  //入力している値と文字が一致する名前を抽出する
	  $searchName = $_POST['name'];
	  $textLength = mb_strlen($searchName,'UTF-8');
	  if($textLength >= 1){
	    // 本来はデータベースからデータを取得するがシンプルにするため、今回はPHPの配列に入れました。
	    $name = ['けんた','けんじ','いさむ','ゆうき','かずや','たける','かずき'];
	    $hit_name = [];
	    for($i = 0;$i < count($name);$i++) {
	      if(preg_match('/^'.$searchName.'/',$name[$i])){
	        array_push($hit_name,$name[$i]);
	      }
        }
	    // JSON形式で送信する
	    $json = json_encode( $hit_name, JSON_UNESCAPED_UNICODE);
	    echo $json;
	  }
	} 
  }else {
    echo '通信失敗';
  }
?>
```
# 補足
## Ajaxのメリット
###(1)ページ遷移なしでWebサーバーと通信できる
例えばお問い合わせフォームで送信したり、サイト内でキーワード検索したりするとサイト全体が更新され書き換えられます。
しかし、Ajaxでは必要な部分のデータだけを送受信できるため、**最小限のデータ分だけWebサーバとやりとり可能であり、高速でWebページの書き換えが可能**になる。

###(2)非同期でWebサーバーと通信できる
同期通信ではサーバからレスポンシブが返ってくるまでブラウザで作業を進めることができません。（ファビコンのとこがグルグル回ってブラウザの更新を待たされる）
一方、Ajaxならばサーバからのレスポンスを待たずに、サクサクとブラウザでユーザーが作業を続けれます。

## 重要用語
Ajaxとは何か?と調べているとよく見る用語をまとめてみました。

###(1)XML
XML = eXtensible Markup Langunage の略。
拡張可能なマークアップ言語でデータをテキストで記述するための言語。
####例

```xml
<food>
 <fruit>桃</fruit>
 <fish>さんま</fish>
 <meet>豚肉</meet>
</food>
```
###(2)XMLHttpRequest(XHR)
Webサーバと通信を行うために使われるオブジェクト。
####メソッドやプロパティの例
| メソッド名| 用途 | 
|-----------|------------|
| open( method,url,async )    | 生成したXHLHttpRequestオブジェクトが要求するサーバのアドレスや通信方法を設定する<br>method : HTTPリクエストメソッドを文字列を指定( POST or GET )<br>url : アクセスするWebサーバのURLの指定<br>async : 通信を非同期に行うかどうかをbooleanで表す( true or false )|
| send( data )  |サーバにリクエストを送るdataの値は<br>POSTメソッド : 取得したいデータを指定すると、サーバから要求したコンテンツを**responseText属性**から文字列で取得できる<br>GETメソッド : nullを指定する| 
| setRequestHeader( header,value )    |XMLHttpRequestオブジェクトからサーバに要求を行うとき、Httpヘッダを設定する<br>header : Httpヘッダの名前<br>value : HTMLヘッダの値を指定        |

| プロパティ名| 用途 | 
|-----------|------------|
|responseText|任意のテキストを取得できる。.txt形式のテキストやXMLなど様々。|
|onreadystatechange|リクエストを行ったXMLHttpRequest属性を調べ、responseTextを用いてデータを取得できる。<br>**readyState属性**からサーバとの通信状態を取得できるのでセットで使う。|
|readyState|XMLHttpRequestオブジェクトの状態を表す**数値**を返す<br>0 : 初期化されていない<br>1 : openメソッドが成功<br>2 : リクエストに成功<br>3 : Httpヘッダを取得<br>4 : 全て完了<br>|
|status|Httpの応答コードを返す。404や200など|
###(3)Ajaxにおいての非同期通信
**JavaScript**がサーバにリクエストを送信し、サーバが**XMLファイル**をブラウザに返す。

→ブラウザ更新に必要なデータだけをXMLを送受信するため、ページ全体のHTMLをやりとりする同期通信に比べてサーバに負担をかけない。

###(4)同期通信
**ブラウザ**がサーバリクエストを送信し、サーバが**HTMLファイル**をブラウザに返す。

→同期通信では全ての情報を通信しているため、サーバへの負荷が高くなるデメリットがある。
 また、ユーザーはリクエストを送信するとサーバがレスポンスを返してページが表示されるまでの間サイトを操作することができず、待つ時間が発生する。
## 参考文献

この記事は以下の情報を参考にして執筆しました。

[ゲーム開発で学ぶ Ajax入門](https://www.amazon.co.jp/%E3%82%B2%E3%83%BC%E3%83%A0%E9%96%8B%E7%99%BA%E3%81%A7%E5%AD%A6%E3%81%B6-Ajax%E5%85%A5%E9%96%80-GAME-DEVELOPER-%E8%B5%A4%E5%9D%82/dp/4797340037)