1.隠れた動作を分析する
といっても、決して難しいことをするのではありません。検索ページindex.htmlをエディターで開いて、ちょっとした悪戯をしてみましょう。9行目のindex.jsの名前を、存在しないファイル名index9.jsに修正して書き戻してください。
<!DOCTYPE html>
<html lang="ja">
<head>
日本の世界遺産
</head>
<?php
include "inc/mysqlmdl.php"; // MySQL用モジュールを組み込む
?>
そして、WebブラウザからWorldHeritageにアクセスしてください。
すると、画面縦方向にタブページがずらりと並んで表示されます。これが何を意味しているか、お分かりになった方も多いのではないでしょうか。
(1)処理速度を改善するためのヒント
これは、index.htmlの<body>タグに記述したコードのすべてが、上から下に向かって順序通りに実行されたことを示しています。
初期状態では「都道府県検索」のタブページが表示されていて、タブをクリックすると表示が切り替わるので、処理されているのは対象になったタブページだけだと感じていたのではないでしょうか。ところが、タブのonClickイベントハンドラが動作するたびに、すべてのタブページの処理と編集が実行されて、該当タブが選択表示されていただけなのです。先ほどjsファイルをアクセスできないようにしたことから、changeTab()メソッドが動作しなくなり裏に隠れた動作が明らかになりました。
ファイル名を正しいindex.jsに戻して、もう一度実行させてください。そして今度は、画面を右クリックして現れるメニューから[ページのソースを表示]または[ソースの表示]を選択してください。表示された内容を見ると、当面の検索には必要でないタブのコードもすべて書き出されているのが分かります。
「タブをワンクリックするたびに、4種類すべてのデータベースを検索して、すべてのタブページが編集されている」、これは実にショッキングな事態ではないでしょうか。
検索種別が4種類と少ないこと、リストボックスの内容がさほど多くないことから処理時間は気になりませんでした。しかし、タブの種類がさらに増え、リストボックス作成対象のデータ件数(レコード数)が膨大になるとどうでしょうか。一般のシステムでは同時に多数のユーザーがアクセスするので、わずかな処理時間の増加がサーバーの負荷を高め、ユーザーの待ち時間を増やすことになります。このアプリケーションは目的どおり動作してはいますが、処理効率面で構造上の問題をかかえていることが判りました。
これを解消するには、選択されたタブ種別のSQL文だけを実行して、必要最低限のHTMLだけを生成させる方法が考えられます。そのコードを考えて、実際にテストしてみてください。結果表示ページresult.htmlのコードが参考になるでしょう。これが実現できれば、処理時間は4分の1近くまで減少するはずです。
実は次節で改良版を取り上げるのですが、この節が一段落したら、各自でコードの改変にトライすることをお勧めします。
(2)コードのスタイル改善のヒント
アプリケーションの構造がシンプルであることから、今回のようなコードは比較的楽に書き進めることができました。また出来上がったコードを読み返すのも苦労ではありません。
しかし、タブの種別が増えたり単位タブあたりの処理の複雑さが増すと、ひたすら処理の流れに従って処理ロジックとHTML生成のためのコードを書くのはたいくつになります。また記述内容が複雑化して分かりにくくなります。これを解消するためにはいくつか方法があります。コードをわかりやすく、タブページ編集の中身をさらに細分化して、データベースのアクセスと結果の編集を分割するような方法が考えられます。
これらの記述を外部ファイルに収納して、そのファイルを実行時に弾力的に組み込むことはさほど難しくないことが、ここまで読み進んだ皆さんには無理なく理解できると思います。これも次節のテーマになるのですが、ぜひ、各自で構想を練ってみてください。
(3)コードの簡潔さと速度を最適化できるか
(2)を実現するための有力な方法として、PHPのinclude文は魅力的です。処理を細分化してファイルに展開しておき、必要な時点で組み込む
しかし、必要の都度ファイルをアクセスすると、それに要する時間が問題になってきます。SDカードやハードディスクのアクセス時間は、決して速くないからです。もっとも、これは膨大なデータ量を扱ったりアクセスが集中する場合に問題になることであって、現時点では杞憂に過ぎないのですが。
ただ、今後大きなテーマに取り組む際には、まずは対象を論理的に適正なまとまりに分割すること、将来の機能拡張や保守性を配慮してわかりやすい構造とコードを書くように努めることがとても大切です。そして、プロセッサーの高性能化と低価格化が進み、高速なSSD(Solid State Drive)などが比較的安価に入手できる現在、ハードウェアによる問題解決の方法も一考の価値ありです。
2.アプリケーションの改善とロジックの整理
先の問題点を改良するために、コードを大幅に書き換えます。それに先だって、検索種別ごとにロジックを整理してみましょう。ドキュメントルート配下に新たなフォルダーWorldHeritage2を作成して、WorldHeritageの内容をそっくりコピーしてください。そしてWorldHeritage2の配下にフォルダーphpを新設してください。このフォルダーに、index.htmlの検索タブページ生成部とresult.htmlの検索・結果編集部を、それぞれPHPで記述して格納することにします。
ロジックの整理には、『Ⅵ. Webアプリケーションの開発①』データベース操作メソッドのライブラリ化で説明した「関数(function)」を使用します。
(1)「検索タブページ生成」コードの作成
createTabPageという名前の関数を呼ぶだけで、タブページを表示するためのHTMLが生成できてしまう、そんな仕組みを考えます。ただし、今度はクリックされた検索種別に必要なHTMLだけを生成させたいので、この関数の第1引数でタブ種別を与え、その後にデータベース操作に必要なデータベース名、利用者ID、パスワードを指定できるようにします。
関数の中身は次の通りです。引数のタブ種別$typeの内容に従って、下位の関数createTabPage1~4を呼び出しています。下位関数が返してくれるはずのHTML文をそのまま呼び出し元に返す、というシンプルな関数ですが、これで必要なHTMLだけを生成する準備ができました。
<?php
/*
* 検索タブページの生成
* $type : タブ種別("tab11~4")
* $db : データベース名
* $id : 利用者ID
* $pwd : パスワード
* 返却値: タブページのHTML
*/
function createTabPage($type, $db, $id, $pwd)
{
switch ($type) {
case "tab1":
return createTabPage1($db, $id, $pwd);
break;
case "tab2":
return createTabPage2($db, $id, $pwd);
break;
case "tab3":
return createTabPage3($db, $id, $pwd);
break;
case "tab4":
return createTabPage4($db, $id, $pwd);
break;
default:
return "";
break;
}
}
下位関数は、引数としてデータベース操作用の情報だけを受けて、データーベースからリストボックス作成用の情報を抽出しHTML文を組み立てています。ここでは都道府県検索と登録年度検索の2つだけを例示しますが、すでに『Ⅶ. Webアプリケーションの開発②』で取り組んだ内容の変形なので、容易に理解できることでしょう。
/*
* 都道府県検索タブページの生成
* $db : データベース名
* $id : 利用者ID
* $pwd : パスワード
* 返却値: タブページのHTML
*/
function createTabPage1($db, $id, $pwd)
{
$buf = "";
$buf = $buf . "都道府県名を選択してください!
";
$conn = openDatabase($db, $id, $pwd);
if ($conn) {
$sql = "SELECT PrefCode, PrefName FROM pref_table ORDER BY PrefCode";
$rs = execQuery($conn, $sql);
$buf = $buf . "
";
$buf = $buf . "";
}
return $buf . "";
}
/*
* 登録年度検索タブページの生成
* $db : データベース名
* $id : 利用者ID
* $pwd : パスワード
* 返却値: タブページのHTML
*/
function createTabPage2($db, $id, $pwd)
{
$buf = "";
$buf = $buf . "対象年を選択してください!
";
$conn = openDatabase($db, $id, $pwd);
if ($conn) {
$sql = "SELECT DISTINCT RegisterDate FROM heritage_table ORDER BY RegisterDate";
$rs = execQuery($conn, $sql);
$buf = $buf . "
";
$buf = $buf . "";
}
return $buf . "";
}
このように、目的とする処理を関数にまとめると、その目的に専念してコードを書くことができます。テスト段階で問題が発生した場合も問題の所在を把握しやすく、他の処理に関係なく改変や調整を行うことが可能になります。
createTabPage3以降を書き進めて(phpのコードなので、終端に"?>"を書くこと)、出来上がったコードはcreateTabPage.phpの名前でphpフォルダーに格納してください。
都道府県名を選択してください!
"; $conn = openDatabase($db, $id, $pwd); if ($conn) { $sql = "SELECT PrefCode, PrefName FROM pref_table ORDER BY PrefCode"; $rs = execQuery($conn, $sql); $buf = $buf . ""; $buf = $buf . ""; } return $buf . "
対象年を選択してください!
"; $conn = openDatabase($db, $id, $pwd); if ($conn) { $sql = "SELECT DISTINCT RegisterDate FROM heritage_table ORDER BY RegisterDate"; $rs = execQuery($conn, $sql); $buf = $buf . ""; $buf = $buf . ""; } return $buf . "
(2)「検索・結果一覧生成」コードの作成
外部から呼ばれる2つの関数で構成します。
最初の関数は、標題部のタイトル文字列を生成するeditTitleです。タブ種別とリストボックスから取得したタイトル名称を引数とし、関数はタブ種別に応じた修飾をして作成した見出しを返却します。
<?php
/*
* 標題の編集
* $type : タブ種別('1'~'4')
* $name : タイトル名称
* 返却値: タイトル文字列
*/
function editTitle($type, $name) {
switch ($type) {
case '1':
return $name . "の世界遺産";
break;
case '2':
return $name . "年登録の世界遺産";
break;
case '3':
return $name . " :その構成資産";
break;
case '4':
return $name . "として登録された世界遺産";
break;
default:
return $name;
break;
}
}
2つめの関数は、指定された条件でデータベースを検索して、検索結果から一覧表のHTMLを生成する関数 searchAndEditDetailです。タブ種別とデータベース操作用の情報、そして検索対象コードを引数としてこの関数を呼ぶと、データースを検索して検索結果を一覧表に編集します。
この関数も先のcreateTabPageと同様にシンプルで、searchAndEditDetail1~4を呼んで、受け取ったHTML文をそのまま呼び出し元に返却します。
/*
* データベースの検索と結果の編集
* $type : タブ種別('1'~'4')
* $db : データベース名
* $id : 利用者ID
* $pwd : パスワード
* $code : 検索コード
* 返却値: タブページのHTML
*/
function searchAndEditDetail($type, $db, $id, $pwd, $code)
{
switch ($type) {
case '1':
return searchAndEditDetail1($db, $id, $pwd, $code);
break;
case '2':
return searchAndEditDetail2($db, $id, $pwd, $code);
break;
case '3':
return searchAndEditDetail3($db, $id, $pwd, $code);
break;
case '4':
return searchAndEditDetail4($db, $id, $pwd, $code);
break;
default:
return "";
break;
}
}
下位関数は、引数としてデータベース操作用の情報と検索キー$codeを受けて、対象テーブルを検索して一覧表を組み立てます。ここでは都道府県検索と登録年度検索の2つだけを例示しますが、これも『Ⅶ. Webアプリケーションの開発②』で取り組んだ内容の変形なので、簡単に理解できると思います。
/*
* データベースの検索と結果の編集
* $db : データベース名
* $id : 利用者ID
* $pwd : パスワード
* $code : 検索コード
* 返却値: 一覧表のHTML
*/
//(都道府県)
function searchAndEditDetail1($db, $id, $pwd, $code) {
$conn = openDatabase($db, $id, $pwd);
$sql = "SELECT DISTINCT HeritageName FROM heritage_table INNER JOIN config_table"
. " ON heritage_table.RegisterNo = config_table.RegisterNo WHERE PrefCode="
. $code . " ORDER BY heritage_table.RegisterNo";
$rs = execQuery($conn, $sql);
$no = 0;
while( $row = getResultSet($rs) ) {
$data = $row['HeritageName'];
$no++;
$tbl = $tbl . "" . $no . " " . $data . " \n";
}
if ($no == 0)
$tbl = $tbl . " ** 世界遺産は未登録です ** \n";
closeDatabase($conn);
return $tbl;
}
//(登録年度)
function searchAndEditDetail2($db, $id, $pwd, $code) {
$conn = openDatabase($db, $id, $pwd);
$sql = "SELECT HeritageName FROM heritage_table WHERE RegisterDate LIKE '"
. $code . "%' ORDER BY RegisterNo";
$rs = execQuery($conn, $sql);
$no = 0;
while( $row = getResultSet($rs) ) {
$data = $row['HeritageName'];
$no++;
$tbl = $tbl . "" . $no . " " . $data . " \n";
}
closeDatabase($conn);
return $tbl;
}
同様にsearchAndEditDetail3・4を書き進めて、出来上がったコードはcreateTabPage.phpの名前でphpフォルダーに格納してください。
(3)検索ページの改変
index.htmlを修正します。冒頭の部分は以前のままで、14行目に先ほど作成したcreateTabPage.phpをincludeで組み込んでください。そしてformタグの次の、カレント・タブ位置保持用の非表示項目<input type="hidden"~の行を削除してください。これに代えて'tab_type'という名前のクッキーを使用します。
続いて、<?php~?>の内容を全面的に書き換えます。
30~33行は検索種別を確定する処理です。issetで'tab_type'という名前のクッキーが設定されているかを調べて、設定されていれば、そこに格納されているカレントのタブ種別を使用します。しかし、最初に起動されたときは初期ページ(都道府県検索タブ)を表示させたいので、呼び出しパラメータが("GET"メソッドで呼び出すときに"?~"の形式で指定できるクエリ文字:Ⅴ章「クライアントサイドの仕組み」を参照)指定されているかどうかをチェックしています。指定されていなければ、初期のタブ種別"tab1"を設定しています。このアプリケーション内でこのページの呼び出す時は、必ず"?callback=yes"というクエリ文字を付けることにしておけば、初期呼び出しとその後の呼び出しを区別できるわけです(したがってクエリ文字自体に特別な意味はありません)。34行は、このようにして確定したタブ種別をクッキーに設定しています。
検索とHTML生成の指示は極めて簡単です。37行目のように、createTabPageが返却するHTML文をechoでブラウザに書き込むだけです。
<?php
include "inc/mysqlmdl.php"; // MySQL用モジュールを組み込む
include "php/createTabPage.php"; // タブページ生成モジュールを組み込む
?>
<body>
<form name="canvas" action="#" method="post">
<h1>日本の世界遺産</h1>
<div class="tabbox">
<?php
//検索種別を設定して
if (isset($_COOKIE['tab_type']))
$type = $_COOKIE['tab_type'];
if ($_GET['callback'] != "yes")
$type = "tab1";
setcookie('tab_type', $type);
//検索種別に対応したHTML生成を行う
echo createTabPage($type, $targ_db, $user_id, $user_pwd);
?>
</div>
</form>
</body>
</html>
以上の変更に伴ってJavaScriptも修正が必要になります。index.jsのchangeTab関数の内容を全面的に書き換えます。9行目では受け取ったタブ種別をクッキーに設定しています。そしてすぐに、location.hrefで"index.html?callback=yes"を指定してindex.htmlを呼び戻しています。
checkSelection1~4では、それぞれ「document.getElementById("current_tab").value = ~」という行を削除してください。
/*
* File name: index.js
* Function: 『日本の世界遺産DB検索システム』 index.html用
* Date written: 2016/06/15
* Author: Marchan
*/
function changeTab(tabname) {
document.cookie = 'tab_type=' + tabname;
window.location.href = "index.html?callback=yes";
}
function checkSelection1() {
var idx = document.canvas.selectbox1.selectedIndex;
if (idx < 0) {
alert("都道府県名を選択してください!");
return;
}
document.cookie = 'type=1';
document.cookie = 'code=' + document.canvas.selectbox1.options[idx].value;
document.cookie = 'name=' + document.canvas.selectbox1.options[idx].text;
window.location.href = "result.html";
}
(4)結果表示ページの改変
result.htmlも大変シンプルになります。
13行目に先ほど作成したsearchAndEdit.phpをincludeで組み込んでください。クッキーから値を取り出す部分は以前と同じですが、標題出力は21~22行のようにシンプルです。検索結果の編集処理も同様で、searchAndEditDetail関数から返された表形式のHTMLをtable文や行見出しなどで挟み、echo文でブラウザに書き出しています。
37行目に記述する[戻る]ボタンでは、onClickイベントハンドラ内で「location.href='index.html?callback=yes'」のようにindex.htmlを呼んでいることに注意してください。
<?php
include "inc/mysqlmdl.php"; // MySQL用モジュールを組み込む
include "php/searchAndEdit.php"; // 検索・編集モジュールを組み込む
//クッキーから種別と選択されたメニューのコード・名称を取得する
$type = $_COOKIE['type'];
$code = $_COOKIE['code'];
$name = $_COOKIE['name'];
//標題を編集してHTML出力する
$thema = editTitle($type, $name);
echo "<h1>$thema</h1>";
?>
<body>
<section id="contents">
<section class="resultTable">
<?php
/*
* 検索・編集して結果をHTML出力する
*/
$tbl = "<br><br><br><table><thead><tr><th>No.</th><th>遺 産 名</th></tr></thead>\n"
. "<tbody>" . searchAndEditDetail($type, $targ_db, $user_id, $user_pwd, $code)
. "</tbody></table>";
echo $tbl;
?>
</section>
<input type='button' value=' 戻 る ' onclick="location.href='index.html?callback=yes'"><br><br>
</section>
</body>
</html>
これで、この改変作業はひとまず終了です。さっそく動かしてみましょう。
「動きは同じだし、何も変わっていない!」という声が聞こえてきそうです。では、検索ページでマウスを右クリックして、例の「ページのソースを表示」を選択してください。
いかがでしょうか? 以前と比べようもないほどコンパクトなHTML文になっているのがわかります。
3.こんな方法も「あり」です
この節はスキップしていただいても差し支えありませんが、プログラム構造に興味を覚えた人たちに、こんな方法もあるということを例示しておきます。WorldHeritage2と同様にWorldHeritage3フォルダーを作成して、同じアプリケーションを別な構造で記述してみましょう。
(1)関数をファイルに外出しする
phpフォルダーに作成したコードを、タブ種別単位に分割してファイルにしてみます。
次の2つは、先ほど作成したcreateTabPage.phpから、都道府県検索と登録年度検索のタブ生成関数を切り出したものです。どちらも関数名を同じcreateTabPageにしていることに注意してください。他の2つの関数も同様に切り出して、それぞれtab1.php~tab4.phpのファイル名でphpフォルダーに収納しておきます。
<?php
/*
* 都道府県検索タブページの生成
* $db : データベース名
* $id : 利用者ID
* $pwd : パスワード
* 返却値: タブページのHTML
*/
function createTabPage($db, $id, $pwd)
{
$buf = "<div id='tab1' class='tab'>";
$buf = $buf . "<p>都道府県名を選択してください!</p>";
$conn = openDatabase($db, $id, $pwd);
if ($conn) {
$sql = "SELECT PrefCode, PrefName FROM pref_table ORDER BY PrefCode";
$rs = execQuery($conn, $sql);
$buf = $buf . "<select id='selectbox1' name='pref_list' size='10'>";
while( $row = getResultSet($rs) ) {
$buf = $buf . "<option value='" . $row['PrefCode'] . "'>"
. $row['PrefName'] . "</option>";
}
closeDatabase($conn);
$buf = $buf . "</select><br><br>";
$buf = $buf . "<input type='button' value=' 検 索 ' onclick='checkSelection1();'>";
}
return $buf . "</div>";
}
?>
<?php
/*
* 登録年度検索タブページの生成
* $db : データベース名
* $id : 利用者ID
* $pwd : パスワード
* 返却値: タブページのHTML
*/
function createTabPage($db, $id, $pwd)
{
$buf = "<div id='tab2' class='tab'>";
$buf = $buf . "<p>対象年を選択してください!</p>";
$conn = openDatabase($db, $id, $pwd);
if ($conn) {
$sql = "SELECT DISTINCT RegisterDate FROM heritage_table ORDER BY RegisterDate";
$rs = execQuery($conn, $sql);
$buf = $buf . "<select id='selectbox2' name='yearfrom' size='10'>";
while( $row = getResultSet($rs) ) {
$month = $row['RegisterDate'];
if (strlen($month) > 4)
$month = substr($month, 0, 4);
$buf = $buf . "<option value='" . $month . "'>" . $month . "</option>";
}
closeDatabase($conn);
$buf = $buf . "</select><br><br>";
$buf = $buf . "<input type='button' value=' 検 索 ' onclick='checkSelection2();'>";
}
return $buf . "</div>";
}
?>
同じように、searchAndEdit.phpの内容も切り出してファイル化します。以下では検索種別が都道府県の場合を例示していますが、他のものも同様に切り出して、phpフォルダーにres1.php~res4.phpのファイル名で書き出します。どのファイルでも、関数名は同じeditTitleとsearchAndEditDetailに統一してください。
<?php
/*
* 都道府県の標題編集
* $name : タイトル名称
* 返却値: タイトル文字列
*/
function editTitle($name) {
return $name . "の世界遺産";
}
/*
* 都道府県検索と結果の編集
* $db : データベース名
* $id : 利用者ID
* $pwd : パスワード
* $code : 検索コード
* 返却値: 一覧表のHTML
*/
function searchAndEditDetail($db, $id, $pwd, $code) {
$conn = openDatabase($db, $id, $pwd);
$sql = "SELECT DISTINCT HeritageName FROM heritage_table INNER JOIN config_table"
. " ON heritage_table.RegisterNo = config_table.RegisterNo WHERE PrefCode="
. $code . " ORDER BY heritage_table.RegisterNo";
$rs = execQuery($conn, $sql);
$no = 0;
while( $row = getResultSet($rs) ) {
$data = $row['HeritageName'];
$no++;
$tbl = $tbl . "<tr><td>" . $no . "</td><td>" . $data . "</td></tr>\n";
}
if ($no == 0)
$tbl = $tbl . "<tr><td></td><td> ** 世界遺産は未登録です **</td></tr>\n";
closeDatabase($conn);
return $tbl;
}
?>
もう何をしようとしているか、お分かりになったのではないでしょうか?
(2)HTMLを変更する
index.htmlとresult.htmlを開いて、それぞれcreateTabPage.phpとsearchAndEdit.phpのinclude文を削除してください。次に、tab1~4.phpを使用するindex.htmlを記述します。
検索種別に対応したファイルをinclude文で組み込んだ後、createTabPage関数を呼んで得たHTML文をブラウザに書き込むだけで処理完了です。
<body>
<form name="canvas" action="#" method="post">
<h1>日本の世界遺産</h1>
<div class="tabbox">
<p class="tabs">
<a href="#tab1" class="tab1" onClick="changeTab('tab1'); return false;">都道府県別</a>
<a href="#tab2" class="tab2" onClick="changeTab('tab2'); return false;">登録年度別</a>
<a href="#tab3" class="tab3" onClick="changeTab('tab3'); return false;">構成遺産内訳</a>
<a href="#tab4" class="tab4" onClick="changeTab('tab4'); return false;">遺産分類別</a>
</p>
<?php
//検索種別を設定して
if ($_GET['callback'] != "yes")
$type = "tab1";
else if (isset($_COOKIE['tab_type']))
$type = $_COOKIE['tab_type'];
else
$type = "tab1";
setcookie('tab_type', $type);
//検索種別に対応したHTML生成を行う
switch ($type) {
case "tab1":
include "php/tab1.php";
break;
case "tab2":
include "php/tab2.php";
break;
case "tab3":
include "php/tab3.php";
break;
case "tab4":
include "php/tab4.php";
break;
}
echo createTabPage($targ_db, $user_id, $user_pwd);
?>
</div>
</form>
</body>
</html>
次にresult.phpの修正です。
クッキーから取り出したタブ種別に基づいてres1~4.phpのひとつを組み込みます。その後はeditTitle関数で標題を編集してecho出力、searchAndEditDetail関数で表形式を整えてブラウザに書き出すだけです。
<?php
include "inc/mysqlmdl.php"; // MySQL用モジュールを組み込む
//クッキーから種別と選択されたメニューのコード・名称を取得する
$type = $_COOKIE['type'];
$code = $_COOKIE['code'];
$name = $_COOKIE['name'];
/*
* 種別に対応した検索・編集ロジックを組み込み
*/
switch ($type) {
case '1': /* 都道府県検索 */
include "php/res1.php";
break;
case '2': /* 登録年度検索 */
include "php/res2.php";
break;
case '3': /* 構成資産検索 */
include "php/res3.php";
break;
case '4': /* 登録種別検索 */
include "php/res4.php";
break;
}
//標題を編集してHTML出力する
$thema = editTitle($name);
echo "<h1>$thema</h1>";
?>
<body>
<section id="contents">
<section class="resultTable">
<?php
/*
* 検索・編集して結果をHTML出力する
*/
$tbl = "<br><br><br><table><thead><tr><th>No.</th><th>遺 産 名</th></tr></thead>\n"
. "<tbody>" . searchAndEditDetail($targ_db, $user_id, $user_pwd, $code)
. "</tbody></table>";
echo $tbl;
?>
</section>
<input type='button' value=' 戻 る ' onclick="location.href='index.html?callback=yes'"><br><br>
</section>
</body>
</html>
(3)それで何がわかったか
phpのinclude文は大変便利で面白い使い方ができます。比較文の中に記述することができますし、インクルードの対象は通常のコードでも関数でもかまいません。include文に与えるのは絶対パスでも相対パスでも大丈夫で、指定された位置に指定されたファイルを読み込んで評価します。
先の2通りのケースを通して、phpのプログラム自体をデータのように読み込んで、ロジックの一部に組み込んで動作させられることがわかりました。これはphpが、ソースコードを逐次解釈しながら実行するインタプリタ型言語だから可能な芸当です。
開発の当初からデータベース操作用のライブラリmysqlmdl.phpを作成して、各htmlの先頭にインクルードして利用しましたが、ここまで関数等を分割してファイルに格納できるとなると、もっと新しい利用方法が見つかるように感じませんか?
それはさておき、よく使う関数などは別ファイルに収納しておき、複数のページで共用できるようにようにしておくととても便利です。あちこちで重複するコードを書くようなムダが省け、開発の効率がアップ。メンテナンスの便利もいいし、コードの品質向上にも役立ちます。
4.これからの展開について
Webアプリケーションが、テキストエディターだけで簡単に開発できることを見てきました。すべてを一から書くことで、動作の仕組みを理解することができますし、コードを少し変更してさらに細かい仕組みに迫れることもわかりました。このような方法は、ソフトウェア開発の基礎やプログラム言語の初歩の学習にもっとも適していると考えています。
ところで、これから何を学習しどのような方向を目指せばいいのか、本稿の最後に少しだけ私見を述べさせていただきます。
(1)中規模システムに挑戦する
さざまな開発ツールやプログラム言語が気になって、なかなかひとつのことに集中しにくい贅沢な環境に取り囲まれた状況です。しかしここ一番、テキストエディターでもうひとふんばりすることをお勧めします。せっかく身についてきたHTML, CSS, JavaScript, PHP, MySQLの知識を、ここで終わりにするのはもったいない。さらに極めるために、少し大きなシステムに挑戦することにしましょう
具体的なテーマとしては、今回開発したアプリケーションを一歩進めて、次の機能を付け加えてください。
○データベースにデータを追加、修正、削除できるページを作成する。
○データベースを誰もが勝手に操作できると危険なので、ログイン画面を設置する。
ログイン画面は比較的簡単に作成できますが、一方でSQLインジェクションへの対策が必要になります。ユーザーIDを入力すべき欄にSQL文を入力すると何が起きるか、恐い実験もやってみましょう。ログインの成否の結果を保持して、いきなりデータベース保守ページにコンタクトできないようにするには、セッション変数を応用してみましょう。
キーボード入力では、誤ったデータを入力させないための様々な対策を考える必要があります。さらに、複数の利用者が同時にデータベースを更新する場合を想定してください。ユーザーに負担をかけない実用的な排他制御をどうするか、入力がバッティングした場合の更新取り消しなどのトランザクション処理もやってみましょう。
たった2つのテーマを追加することで、望ましいユーザーインターフェイス、エラーデータの排除、セキュリティ対策、データベースの高度な利用についての理解を深められます。こうして身についた知識・技能は、他の開発環境でも十分活用することができます。
(2)他の言語やテクノロジーに視野を広げる
PHPもJavaScriptも大変使いやすい言語です。どちらもスクリプト言語と呼ばれるもので、データの型チェックがゆるいことから、簡潔で柔軟な記述ができます。また両言語ともインタプリタ言語なので、エディターで手軽にコードを変更しながら動作を確かめることができます。横道にそれるのは大いに結構、あれこれの実験から見えてくるものは多く、発見に繋がります。
そして両言語は、オブジェクト指向の機能をもっているので、この際、これも基本的な事項をマスターしてしまいましょう。今回のコードを記述しながら、名前のスペルミスで同名を使用して動作がおかしくなったり、ファイルの関数内で使った名前はどの範囲で有効なのか迷ったりした方もいたのではないでしょうか。オブジェクト指向では、このようなデータに付ける名前の有効範囲を制限することができます。
また、オブジェクト指向プログラミングのもっとも大きな特徴は、ロジックの内部構造やデータをカプセル化して外部から遮蔽できることにあります。クラスやインスタンス、カプセル化、メソッドなど、その基礎をぜひマスターしましょう。それによって、まとまりのあるロジックをプログラム部品として、弾力的かつ安全に利用することが可能になります。
このコーナーではほとんど解説できなかったLinuxについての知識、例えばファイル管理やディレクトリ管理とパーミッションのこと、パッケージ利用、プロセス管理やサービス管理、ユーザー管理などについても基本的なことを把握しておきたいですね。
さらに、これは少し敷居が高いかも知れませんが、低レベル言語としてのC言語、これから発展した高級なC++、C#、Javaなど、言語構文やデータ型チェックが厳密なものもぜひ手掛けることをお勧めします。ついでながら、私は早い時期にC言語をマスターしたことで、その後の他言語の習得やオブジェクト指向の理解にとても役だったことを付記しておきます。
(3)大規模開発の世界