例1a

名前を入れて送信ボタンを押してください。名前は非同期にサーバに送られ,サーバからは挨拶と現在のUNIX時刻(1970年元旦からの秒数)が返されます。ページ全体を読み直すわけではないので,たいへん高速です。

お名前:

解説

クライアント側

まずはこのページのソースをご覧ください(エンコーディングはUTF-8です)。headの中の

<script>
……
</script>

の部分がJavaScriptのプログラムです。ここでは,そのずっと下のformの部分から見ていきましょう。

<form onsubmit="doit();return false;">
<p>お名前:<input id="user">
<input type="submit" value="送信"></p>
</form>

<div id="result"></div>

このformに書き込んで「送信」ボタンを押すと,onsubmit で指定されている doit(); return false; が実行されます。ここで return false; はブラウザの標準の動作(この場合formのsubmitボタンの動作)をさせないための常套手段です。doit() の定義は次のようになっています(多少簡略化しましたが後で説明します)。

<script>
function doit() {
  const req = new XMLHttpRequest();
  if (req == null) {
    document.getElementById("result").innerHTML = "<p>未対応ブラウザです。<\/p>";
  } else {
    req.onreadystatechange = function() {
      if (req.readyState == 4 && req.status == 200) {
        document.getElementById("result").innerHTML = req.responseText;
      }
    };
    const u = encodeURIComponent(document.getElementById("user").value);
    req.open("POST", "ex1.php", true);
    req.setRequestHeader('Content-Type', 'application/x-www-form-urlencoded');
    req.send("user=" + u);
  }
}
</script>

まず,新しい XMLHttpRequest オブジェクト(サーバと非同期通信するための仕組み)を生成し,それを req という変数に代入しています。

これに失敗すれば(req == null なら),<div id="result"></div> の中に <p>未対応ブラウザです。</p> というHTMLを書き込むだけで終わります。

失敗しなければ,req というオブジェクトの onreadystatechange というプロパティ(JavaやC++の用語ではフィールド)に無名の関数を代入しています。 この関数はコールバック関数と呼ばれ,何かイベントが発生すると呼ばれます。 ここでは req というオブジェクトが作業を遂行するにつれ,その状態 req.readyState が0→1→2→3→4と変化するのですが,その変化のたびに呼ばれる関数を定義しています。 作業が完遂されたなら req.readyState == 4 になりますが,そのときのHTTPステータスコード req.status が200(OK)ならば,サーバから送られたテキスト req.responseText<div id="result"></div> の中に表示します。

続いて,<input id="user"> の値(つまりユーザが打ち込んだお名前)を取り出し,これをURLエンコード(アスキー以外の文字を % に続く16進2桁に直すこと)して,それを変数 u に代入しています。

続いて,req.open で,POSTメソッドでサーバの ex1.php を呼び出しています(最後の true は非同期呼出しを意味します)。 このPOSTメソッドでは Content-Type: application/x-www-form-urlencoded というヘッダを使います。

最後に,user= に続けてさきほどのURLエンコードした値を送ります。

これで doit() 関数は終わりますが,コールバック関数が設定されていますので,上に述べたように,状態が変わればそちらのほうが呼び出されることになります。

サーバ側

サーバ側には,この ex1.html と同じディレクトリに次の ex1.php というファイルがはいっています:

<?php
  header('Content-Type: text/html; charset=UTF-8');
  if ($_POST['user']) {
    echo '<p>', htmlspecialchars($_POST['user']), 'さんこんにちは。</p>';
  }
  echo '<p>だたいまのUNIX時刻は ', time(), ' 秒です。</p>';
?>

これは,POSTメソッドで受け取った user の値を htmlspecialchars() で無害化(<&lt; に直すなど)してから挨拶に直して,現在のUNIX時刻(1970年元旦からの秒数)とともに送り返します。

この場合 if ($_POST['user'])user=... がセットされていて,なおかつ空文字列 "" でも "0" でもないことを意味します。もし 0 と打ち込まれたら空欄と判断されてしまいますので,厳密には if (isset($_POST['user']) && $_POST['user'] != '') とすべきかもしれません。