例1

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

解説

クライアント側

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

<script type="text/javascript">
// <![CDATA[

// ]]>
</script>

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

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

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

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

function doit() {
  var 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;
      }
    };
    var 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);
  }
}

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

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

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

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

ところで,上のプログラムは実は単純化されています。 XMLHttpRequest() が定義されていないInternet Explorerのために,次のような関数を作って,場合分けしています。

function newRequest() {
  var x = null;
  if (window.XMLHttpRequest) {  // Firefox, Opera, Safari, ...
    x = new XMLHttpRequest();
  } else if (window.ActiveXObject) {
    try {
      x = new ActiveXObject("Msxml2.XMLHTTP");  // IE6
    } catch (e) {
      try {
        x = new ActiveXObject("Microsoft.XMLHTTP");  // IE5
      } catch (e) {
        x = null;
      }
    }
  }
  return x;
}

実際の doit() ではこれを呼び出しています:

  req = newRequest();  // var req = new XMLHttpRequest(); の代わり

サーバ側

サーバ側には,この 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'] != '') とすべきかもしれません。

注意


奥村晴彦

Last modified: 2007-07-30 12:39:14