4.2.8.検索結果の表示

 最後に検索結果を出力する画面です。ある条件によりDB検索を行った結果は、一般に
その件数を予測できません。クライアント側に対して大量のデータを一度に返してしま
うのは、ネットワーク負荷や画面の応答速度の面からも避けるべきです。出力データ件
数が多い可能性がある場合、ページ制御を行うことを考慮する必要があります。
 zip_display()に渡す引数は、検索結果全体を一定の行数で区切り、その中の何ペー
ジ目を表示するのか指示する数値です。先頭のページなら0になります。

[zip_display.inc]
 1  <?php
 2  //
 3  //  検索結果の表示
 4  //  引数:ページ番号
 5  //
 6  function    zip_display($page)
 7  {
 8      if (DEBUG)  {
 9          print "zip_display($page)<br>\n";
10      }
11      $type   = $_POST['type'];
12      $zip7   = $_POST['zip7'];
13      $pref_j = $_POST['pref_j'];
14      $city_j = $_POST['city_j'];
15      $count  = $_POST['count'];
16      $db = sqlite_open(DB) or die(DB . " がオープンできません。\n");
17      $select_phrase = "SELECT zip7,pref_j,city_j,town_j FROM zip ";
18      if ($type == 1) {       //  郵便番号で検索
19          $where_clause = "WHERE zip7 LIKE '$zip7%'";
20      } else  {               //  住所で検索
21          $where_clause = "WHERE 0=0";
22          if (strlen($pref_j) > 0)  {
23              $where_clause .= " AND pref_j = '$pref_j'";
24          }
25          if (strlen($city_j) > 0)  {
26              $where_clause .= " AND city_j = '$city_j'";
27          }
28      }
29      //
30      //  新規条件指定時(セッションデータとして保存)
31      //
32      if ($page == 0) {
33          $sql = "SELECT COUNT(*) FROM zip " . $where_clause;
34          $ar = sqlite_array_query($db, $sql, SQLITE_NUM);
35          $count = $ar[0][0]; //  新しい条件に該当する件数
36          $_SESSION['type']   = $type;
37          $_SESSION['zip7']   = $zip7;
38          $_SESSION['pref_j'] = $pref_j;
39          $_SESSION['city_j'] = $city_j;
40          $_SESSION['count']  = $count;
41  if (DEBUG)  {
42      print "\$_SESSION[] = "; print_r($_SESSION); print "<br>\n";
43  }
44      }
45      $sql = $select_phrase . $where_clause
46           . " LIMIT " . RECORD_PER_PAGE
47           . " OFFSET " . $page * RECORD_PER_PAGE;
48      //
49      //  ページ制御部分の表示
50      //
51      $pages = $count / RECORD_PER_PAGE;          //  ページ数
52      if ($pages > 1) {
53          print "検索結果ページ:";
54          for ($i=0; $i<$pages; $i++) {
55              if ($i == $page)    {
56                  printf(" %d\n", $i+1);
57              } else  {
58                  printf(" <a href=\"{$_SERVER['PHP_SELF']}?page=%d\">%d</a>\n",
59                      $i, $i+1);
60              }
61          }
62          if ($page+1 < $pages) {
63              printf(
64              " <a href=\"{$_SERVER['PHP_SELF']}?page=%d\">次ページ</a><br>\n",
65              $page+1);
66          }
67      }
68
69      if (DEBUG)  { print "$sql<br>\n";   }
70
71      $res = sqlite_query($db, $sql);             //  SQL の発行
72      $rows = sqlite_num_rows($res);              //  結果の行数
73      if ($rows > 0)  {
74          print "<table border>\n"
75              . "<tr><th>郵便番号<th>都道府県<th>市区町村<th>町域</tr>\n";
76          for ($i=0; $i<$rows; $i++)  {
77              $row = sqlite_fetch_array($res, SQLITE_ASSOC);
78              printf("<tr><td>%s<td>%s<td>%s<td>%s</tr>\n",
79                  $row['zip7'], $row['pref_j'], $row['city_j'], $row['town_j']);
80          }
81          print("</table>\n");
82      } else  {
83          print "該当するデータはありません。\n";
84      }
85      sqlite_close($db);
86      print "</body></html>";
87  }   //  zip_display();
88  ?>

 16行目でデータベースを開き、17行目ではレコードを抽出するためのSQL文の先頭部
分を作って$select_phraseにセットしておきます。18〜28行目では、SELECTで指定する
WHERE句だけを、別途$where_clauseにセットします。
 32〜44行目では、$where_clauseで抽出されるレコード全体の件数を求めて、現在の
抽出条件とともにセッション変数に保存します。この処理は当該スクリプトが呼び出さ
れるたびに行っても正しく動作しますが、速度的に不利なので、先頭ページ表示時のみ
で行われるように条件を限定しています。
 45〜47行目で実際に抽出をかけるためのSQL文を生成します。この関数の引数である
$pageが絞り込み条件として使われています。WHRE句による抽出されたレコードの集合
(レコードセット)の中からOFFSETで指定したレコード番号(先頭は0)から数えて、
LIMITで指定したレコード数分だけのレコードを取り出しています。
 次に、51行目では検索結果が全部で何ページあるのかを算出しています。これが1ペ
ージに収まるのであれば問題ありませんが、2ページ以上にまたがる場合、図4-7のよう
に、検索結果が全部で何ページあるのか、また現在何ページ目を表示中なのかという、
ページ制御用のナビゲータを表示します(52〜67行目)。
 やっと準備完了です。71行目でSQLを発行し、次の行で取り出した行数を取得します。
73〜84行で、行数分だけループしながらHTMLの表を構成しています。