Ajax と PHP で画面遷移しないフォームを作成する方法

はじめに

実務にて、jQuery を使わない JS(JavaScript)の Ajax と PHP で非同期通信を利用した画面遷移させないフォームを作成する作業があり、それを解決した情報になります。Web 開発の初心者、初学者の方にもわかりやすいように、ソースコードを編集してサンプルを公開しています、ご参考になれば幸いです。

サンプルのソースコードでは、簡単なアンケートフォームを作成しています。

検証環境

サンプル

解説

Ajax とは

既に、Ajax を理解している方は読み飛ばしちゃってください。

Ajax は、2005 年 2 月 18 日に IA(information architect)の Jesse James Garrett によって作られた言葉で、Asynchronous JavaScript And XML(非同期な JavaScript と XML)の頭字語です。

Ajax とは、JavaScript で非同期に Web サーバーへ要求(リクエスト)を送り、応答(レスポンス)から XML、又は JSON データを受け取り、その通信結果でもって DOM(Document Object Model)でページを動的に書き換える手法のことです。

よく間違われているのですが、Ajax は技術のことではなく、既存の技術(HTML, XHTML, CSS, JavaScript, XMLHttpRequest, DOM, XML, XSLT)を組み合わせた 1 つのやり方のことです。

非同期通信とは

既に、非同期通信を理解している方は読み飛ばしちゃってください。

非同期通信とは、Web サーバーからの応答(レスポンス)を待たないで処理を続ける通信のことです。逆に、同期通信とは、Web サーバーからの応答(レスポンス)を待つ通信です。

非同期処理と同期処理の違いは、料理に例えてみるとイメージしやすいと思います。

例えば、焼き魚の調理中に味噌汁を作ることになった場合、非同期処理は焼き魚の調理を中断しないで味噌汁を作ります。同期処理は焼き魚の調理を終わらせてから順番に味噌汁を作ります。

よくある質問に「非同期処理と並列処理と並行処理の違いは何ですか?」という内容があります。

並列処理とは、複数の作業を複数人が同時に進めることです。例えば、運動会の徒競走で「位置に着いて、よ〜いドン!」の合図で走者が一斉にスタートするようなイメージです。

並行処理とは、複数の作業を一人が切り替えながら進めることです。例えば、コンビニの深夜営業を一人の従業員に全て任せる(ワンオペレーション)ようなイメージです。

非同期処理とは、話している場所が違うことがわかると思います。

つまり、並列処理の中で非同期処理が行われるようなことが有り得るということですね。例えば、パン食い競走のようなイメージでしょうか。

本題

本題に入ります。

Ajax を実現するよくある手法は下記の 3 つです。

  1. XMLHttpRequest を使用する
  2. Fetch API を使用する
  3. jQuery.ajax() を使用する

各手法の対応ブラウザーは下記になります。

  1. XMLHttpRequest は ブラウザーの互換性 より、基本的に未対応ブラウザはありません。
  2. Fetch API は caniuse.com の ブラウザーの互換性 より、最新では IE 11 とOpera Mini が未対応です。
  3. jQuery は Browser Support より、基本的に未対応ブラウザはありません。

今回は Fetch API を使用しています。理由は、XMLHttpRequest だとコードが少し複雑になってしまうことと、JQuery を使うほどではないことです。

Fetch API でリクエストする方法は、下記のようにシンプルです。

const request = 'https://example.com/test.json'

fetch(request)
.then(response => response.json())
.then(json => {
  // 処理
})

説明すると、fetch() の第 1 引数に取得したいリソースのパスを渡して、返ってきた Response を含む Promise オブジェクトから Response.json() を実行して JSON を抽出しています。

Promise オブジェクトとは、非同期処理の結果を表すオブジェクトで、下記の 3 つの状態があります。

  • 待機(pending): 初期状態
  • 履行(fulfilled): 処理成功
  • 拒否(rejected): 処理失敗

then() は、Promise の状態が履行の時にコールバック関数を取ります。つまり、Promise の状態が履行だったら処理を進めますねということです。

因みに、コールバック関数とは、関数の引数に渡される関数のことです。

PHP に POST パラメーターを渡したい時は、下記のように Web APIFormData を使用します。

<form id="form">
  ...
</form>
const request = 'https://example.com/test.json'
formData = new FormData(form)

fetch(request, {method: 'POST', body: formData})
.then(response => response.json())
.then(json => {
  // 処理
})

説明すると、FormData のコンストラクターに <form> 要素を指定して、fetch() のオプションに method(リクエストするメソッド)と body(リクエストに追加したい本文)を指定することで POST パラメーターを渡すことができます。

あとは、fetch() の第 1 引数に指定した PHP ファイルで $_POST から値を受け取るだけです。

PHP から JS に値を渡したい時は、下記のように header で Content-Type を JSON に指定して、json_encode で値を JSON 形式にエンコードしてから echo で出力します。

  header('Content-type: application/json');
  echo json_encode([
    ...
  ]);

下記のように抽出した JSON を console.log() で Web コンソールに出力すると正常に処理できているか確認しやすいです。

fetch(request, {method: 'POST', body: formData})
.then(response => response.json())
.then(json => {
  console.log(json)
})

要となる Ajax の部分ができてしまえば、あとは非同期通信の結果によって Element.classListadd()remove() で HTML を書き換えれば良いだけです。この辺りは、サンプルのソースコード(questionnaire.js)を見ればわかると思います。

まとめ

Ajax を実現する方法は下記の 3 つ。

  1. XMLHttpRequest を使用する
  2. Fetch API を使用する
  3. jQuery.ajax() を使用する

IE 対応が必須でなければ Fetch API でシンプルに非同期通信ができる。

PHP から JS に値を渡す時は JSON で出力する。

非同期通信の結果によって HTML を書き換える。

以上です。

おわりに

サンプルのソースコードを再利用する際は、要件定義やコーディング規約にお気を付けください。