今回は、トップページの右側に貼ってある「The Sims 2 Download」っていう自前のページについての話題です。
このページ、The Sims 2というゲームで使用できる自作住宅を紹介しているページなのですが、住宅が増える度にhtmlをコピーして追加してきたため、現時点で住宅数75、htmlファイルは2,151行、貼付けてある画像ファイルは261個と、Webページの1ページに納めるには非常識な状態になっています。自分でhtmlを書いているためずいぶん前から認識はしていたのですが、ここ最近、いくらなんでもこのままではヤバいと思うようになり、9月の連休も手伝って重い腰を上げることにしました。
そこで、どうするかということですが、この手のページは表示する項目が決まっており、いわゆるネットショッピングの商品選択ページのようなものであるため、データベースを利用するのが向いています。また、htmlが重複する部分が多いため、データベースを読んで表示するCGIを作ってしまえば以降手間がかかりません。ってことで、データベースには1つのデータベースファイルで済み、バックアップが容易なSQLiteを、CGIの方は流行りのPHPを使ってページを改良することにしました。
1)データベースを作成しようと...
あ〜、長い前置きだったw。で、データベースを手軽に作成しようと、Macでも使えるSQLiteのツールをsqlite - Management Toolsで探してみました。
結論から言うと、色々と試してみましたが良いのが無かったという状況です。というのは、文字や数字は問題ないのですが、htmlのタグを含んだ文字列をそのままデータベースに入れようとするとWebページのように表示され、文字列として修正できない状況になるためです。
と、いうことで、結局データベースを作るツールからPHPで書く羽目に...。
2)データベース追加・編集ツールの作成
あ〜辛気くさいw。便利なツールが自由に使える状態になっているかと思っていたら、こんなものから自分で作ることになるとは...。なんだかんだ言いつつ苦労しながらも何とか作れたので、作成時のポイント等を紹介します。なお、LaCoocanのレンタルサーバーはPHP5になっています。
参考:PHP マニュアル SQLite/SQL Syntax
a)データベース作成スクリプト
データベースは1つのテーブルに次のフィールドを設定しました。
Column | Type | Comment |
id | INTEGER PRIMARY KEY | 主キー |
date | DATE | 作成日 |
type | TEXT | 住居/公共の別 |
width | INTEGER | 区画の幅 |
depth | INTEGER | 区画の奥行き |
price | INTEGER | 価格 |
title | TEXT | 名称(「'」及び「"」有り) |
text | TEXT | 本文(「'」及びhtmlのタグ内に「"」有り) |
note | TEXT | 注記(「'」及びhtmlのタグ内に「"」有り) |
file_name | TEXT | ファイル名 |
file_url | TEXT | ファイルのURL |
pict_url | TEXT | サムネイルのURL |
ep01 | BOOLEAN | 拡張パック使用の有無 |
ep02 | BOOLEAN | 〃 |
ep03 | BOOLEAN | 〃 |
... | ... | |
PHPからデータベースファイルとそのテーブルを作るのは簡単です。DB::connect()でデータベースに接続し(ファイルがなければ作成される)、query()でSQLコマンドを発行すると作成されます。
require 'DB.php';
$db = DB::connect('sqlite://:@localhost/データベースファイル名');
if (DB::isError($db)) { die("Can't connect: " . $db->getMessage()); }
$q = $db->query('CREATE TABLE lot (
id INTEGER PRIMARY KEY,
date DATE,
type TEXT,
width INTEGER,
depth INTEGER,
price INTEGER,
title TEXT,
text TEXT,
note TEXT,
file_name TEXT,
file_url TEXT,
pict_url TEXT,
ep01 BOOLEAN,
ep02 BOOLEAN,
ep03 BOOLEAN,
... )');
if (DB::isError($q)) { die('Query Error: ' . $q->getMessage()); }
b)データベース編集スクリプト
こっちは上ほど簡単ではありません。リスト表示、新規作成、編集、削除の機能を持つスクリプトを書くのですが、前述のhtmlのタグを含む文字列をそのまま入れようとする箇所(正確には「'」及び「"」のデータが入る箇所)で見事に引っかかりました。テキストフィールドに「'」や「"」があると、保存時に「\」で自動的にクォーティングされるのですが、編集を繰り返す度に重ねてクォーティングされて「\」だらけになってしまうというものです。
クォーティングはSQLの実行時に必要で自動的に行われるのはいいのですが、解説本にはhtmlをフォームで編集してデータベースに保存するということを前提にしていないため対処方法が載ってない(よく読んでないせいかもしれんがw)。結局、いろいろと試行錯誤をした結果、編集フォームに出す前に前回クォーティングされた「\」をstripslashes()で取り除いて、編集フォームに表示することで解決しました。
...
$q = $db->query("SELECT * FROM lot WHERE id = $id");
if (DB::isError($q)) { die('Query Error: ' . $q->getMessage()); }
$row = $q->fetchRow();
...
$title = stripslashes($row[6]);
$text = stripslashes($row[7]);
$note = stripslashes($row[8]);
...
print "<input name=\"title\" value=\"$title\" />\n";
print "<textarea name=\"text\">$text</textarea>\n";
print "<textarea name=\"note\">$note</textarea>\n";
...
あと、データベースへ書き込む時に、データ内に「'」が含まれているとエラーなるため、プレースホルダを使っています。これはquery()の値を入れたいところに「?」を書いて、2番目の引数で値を渡します。後はデータベースがうまく(何を?w)やってくれるそうです。
...
$q = $db->query("INSERT INTO lot (
id, date, type,
width, depth, price,
title, text, note,
file_name, ...
) VALUES (
'$id', '$_POST[date]', '$_POST[type]',
'$_POST[width]', '$_POST[depth]', '$_POST[price]',
?, ?, ?,
$_POST[file_name]', ...
)", array($_POST['title'], $_POST['text'], $_POST['note']));
if (DB::isError($q)) { die('Query Error: ' . $q->getMessage()); }
...
次回は、Webで表示するスクリプトの作成です。