Home > PHP

DBをPHPで扱う時のルーチン

2011.08.03 0:47
 前回の全文検索の続きですが、結構軽々動くMySQL操作のクラスを作りました。MySQLとPHPの感触というのはちょっと変な感じであんまり慣れないのですが、数万件、数億件のデータベースも難なく扱えるというのはちょっとなんかいい感じです。実際問題としてかつては官庁関係とか役所とかしか扱えなかったようなデータベースが普通に一般市民も扱えるなんてちょっといい時代になってきたなと思います。
 昔ながらのプログラマーにとっては当たり前のことですが、相当量のデータを扱う際にはwhileを使います。私の周囲のいわゆるWebデザイン系の自称プログラマーの人々はどうしてだかWhileを使わないんです。理由はわかりません。foreachも使いません。これも理由がわかりません。何故だかforを使います。私としてはforの使いどころが全くわかりません。なぜならwhileもforeachも黙っていても最後まで自動的に処理してくれるし、空っぽになったら自動的に止まってくれるので特にforを使う理由がわからんのです。ここでもwhileを使ってデータベースを処理しています。
 コアになる考え方は、数万件、数億件、更に1つのレコードにあるデータ型がtextだったりして数千文字もあるような場合には、メモリに駐屯するデータを少なくする必要があります。先ほど3万件あるデータベースで"佐藤"が含まれる文字列を検索してみたら238件もありました。30万件だと2000近くあるということになるんでしょうか。2000のレコードが拾われたというのもかなりの量といえなくもないですが、そんなかなりの量に対応する際には、検索結果のデータを寸断して分割してやる必要があります。寸断したデータはページ送りにしてひとまとまりにしておく必要があります。この機能のコアを作っておけば後々かなり便利になるのではないかと思いました。

Download :: db_core_system.php

設定情報

 DBに接続する際には様々な情報が必要です。セキュリティーがしっかりしているのでいろいろと情報が必要となるわけですが、その設定情報はサーバーによってまたあるいは接続DBによってそれぞれ違うのでできるだけ汎用的でありたいと考えて、3つの接続方式で望んでいます。
 設定する情報は、
DBのホスト名 $default_db_host
DBのユーザー名 $default_db_user
DBのパスワード $default_db_password
DB名 $default_db_name
DBの文字コード $default_db_charset

接続後は、
処理対象になるテーブル名
public $default_table_name;

そして、先に解説した通り、ページ送りのインデックス数
$page_pointer_renge
1ページに表示されるレコード数
$page_renge

接続情報

DBへの接続情報の設定は、defineで設定したファイルを読み込んでプロパティーに設定する。__construct();
define ('default_db_host', "localhost");
define ('default_db_user',"mydb");
define ('default_db_password',"*********");
define ('default_db_name',"mydb");
define ('default_charset',"utf8");
 最後の文字コードはデフォルトでUTF-8になっているので、設定しなくてもいい場合はスキップしてください。
それに失敗したら、コンストラクタの引数[$array]から読み込む。
これはオブジェクト生成時にnewのところで配列を与えてやります。
$db_information =array('localhost','mydb','********','mydb','utf8');
$object_db = new db_core_system($db_information);
という具合です。
$db_information[0] = 'localhost';
$db_information[1] = 'mydb';
$db_information[2] = '********';
$db_information[3] = 'mydb';
$db_information[4] = 'utf8';
ここでも最後の文字コードセットはUTF-8の場合は省略しても構いません。

ここまで更に設定していない場合は、プロパティーを直接見ることになります。class内に直接設定してしまうか(デフォルトは空になっています。)、オブジェクト生成後に外部からプロパティーを上書きして設定します。
public $default_db_host;
public $default_db_user;
public $default_db_password;
public $default_db_name;
public $default_charset = 'utf8';
という風に設定されています。

テーブルの指定

 テーブルを指定しないと動きません。指定できるテーブルは1つだけです。
処理対象になるテーブル名
$default_table_name
publicなプロパティーなので外部からもオーバーライドできます。デフォルトは空になっています。

ページ送りの設定

 先ほど前述したようにDBのデータ量が多いと動かなくなるのでページを分割して表示するということを説明しましたが、ここではその設定をします。まず、1ページ内に表示されるレコード数。続いてそれらで分割されて生成されるページのインデックスリンクの数量の設定です。DBの量を見ながら、または表示するという場合のデザインそのものを考慮しながら設定されるべきだと思います。世間では表示数をプルダウンなんかで変更できるようになっていたりますが、それも1つの方法です。
ページ送りのインデックスリンク数 $page_pointer_renge
1ページに表示されるレコード数 $page_renge

実行

 関数実行は2つだけです。
DBにコネクトしてあげる。
テーブルにSQL文を与える。

$return_db = $object_db->db_connect_core();
if ($return_db) {
  $sql_core = "select * from $object_db->default_table_name where text__company1 like '%佐藤%'";
  $object_db->page_number = $_GET['page_number'];
  $return_array = $object_db->table_core($sql_core);
}
注意点は、$object_db->page_numberに$_GET['page_number'];を与えてあげることです。これやらないとページ遷移しないので要注意。GETの添字もこれでもう固めてしまっているのでこれ以外はエラーにならないけど期待した動作になりません。

結果

 これらの情報を与えて実行してやると、たくさんの情報が返ってきます。返ってくる情報は、
<< 一番最初のページに戻るpublic $page_start_point;
< 1つ前に戻るpublic $page_before_point
インデックスのリンク(ページ番号)public [array[$page_bar]]
> 1つ後に進むpublic $page_after_point
>> 最後のページに進むpublic $page_end_point
です。もうリンクにして返してしまっているのでそのまま使えます。画像とかにしたい人にとってはちょっと野暮かもしれないので、適当に変数に組み込んでみてください。

最も大切なDBのレコード情報は、
public $display_record;
で返ってきます。オブジェクトで取り出すこともできるし、SQL文実行時の
$object_db->table_core($sql_core);
の返り値としても取り出すことができます。注意点は2次元配列です。1次元にレコード数、2次元にレコードデータが入っています。2回ループさせないとインデックスの番号しか出てきません。

余談ですが、
public $all_record;
で検索結果のヒット数が取得できます。なんかの目安にはなるかと思います。

実行結果の例
<?php
include("./db_core_system.php");
$db_information =array('localhost','mydb','*********','mydb','utf8');
$object_db = new db_core_system($db_information);

# DB connect information
$object_db->default_table_name = 'kikakujuku_customer'; # 選択テーブル
$object_db->page_renge = '4'; # 1ページのレコード[row]表示数
$object_db->page_pointer_renge = 10; # ページ送りインデックスリンクのページ表示数
$return_db = $object_db->db_connect_core();
if ($return_db) {
  $sql_core = "select * from $object_db->default_table_name where text__company1 like '%佐藤%'";
  $object_db->page_number = $_GET['page_number'];
  $return_array = $object_db->table_core($sql_core);
}
print "<h2>表示結果</h2>";
# ページ送りの表示
print $object_db->page_start_point." ";
print $object_db->page_before_point." ";
foreach ($object_db->page_bar as $k=>$page_number_link) {
print "$page_number_link ";
}
print $object_db->page_after_point." ";
print $object_db->page_end_point." ";

# SQL文実行結果のレコード表示
foreach ($object_db->display_record as $number=>$row) {
  print "<span style='color:red;'>[$number]</span>";
    foreach ($row as $k=>$v) {
  print "$k=>$v";
}
print "<br />\n";
}
?>

これだけでは、かなりださいので拡張機能をいろいろつけるといい感じになります。拡張機能は後ほど。
直し所も多数あって、実はページ送りのためのGETの値は、基幹URLみたいなものと結び付けないと本番で使う際にはかなり不便になるかと思います。Rootの設定を読み込む使用にしないとダメです。







プロフィール



  • Name :: 山上オサム ♂(39)
  • Hobby :: 武術
  • Work :: Web Designer