PEAR DB
PHPでDB操作は欠かせないものだと思います。そのままでも接続が簡単に行えますがPEAR DBを利用して更に簡単に行いたいと思います。
ここでは、よく使うスタイルを紹介します。
DBの接続処理
DBの接続処理をクラスにまとめておき、PEAR DBのオブジェクトをすぐに使えるようにしています。以下の例はDo You PHP?さんのサイトにあるPHP4でデザインパターン(Singleton編)を
参考に作ったものです。(ほぼコピー&ペースト)
接続情報(DSN)をあまり変更しないプログラムなどでは有効に使える
クラスだと思います。
require_once ('DB.php'); /** * データベースクラス * * @author 高橋 裕志郎 <yujiro@rakuto.net> * @package RSL_db * @access public * @version 1.1 */ class RSL_db { /** * DB接続オブジェクト * @access private * @var object */ var $objdb; /** * インスタンス生成 現在の接続を返す * * @access public */ function &getInstance() { static $_singleton; if ($_singleton === null) { $_singleton = new RSL_db(); } return $_singleton->getObjDB(); } /** * コンストラクタ * * @access public */ function RSL_db() { $dsn = array ( 'phptype' => 'sqlite', 'database' => DB_NAME, 'mode' => DB_MODE ); $this->objdb = DB::connect($dsn); /* エラーチェック */ if (DB::isError($this->objdb)) { echo $this->objdb->getMessage(); } } /** * DB接続オブジェクトの取得 * * @access public DB接続オブジェクト * @return object */ function &getObjDB() { return $this->objdb; } }/* RSL_dbの終了 */ /** * データベースとの接続を破棄する * * @access public */ function destroyDBConnect() { $objdb =& RSL_db::getInstance(); if ($objdb){ $objdb->disconnect(); } } register_shutdown_function("destroyDBConnect"); function _main() { $objdb =& RSL_db::getInstance(); }
SELECT以外の処理
SELECT以外のクエリを判定するメンバ関数が用意されています。DB::isManip($query)
クエリを実行した後は以下の関数で本当に処理がされたかを調べます。
クエリ内容が正しくてもDBに反映されないこともあります。
大抵はSQL文がオカシイ場合がほとんどですが……。
$objdb->affectedRows();
require_once ('DB.php'); require_once ('rsl_db.php'); function manip() { $objdb =& RSL_db::getInstance(); /* テーブルの作成 */ $query = <<<QUERY CREATE TABLE account_tbl ( id INTEGER NOT NULL, name VARCHAR(64) NOT NULL, email VARCHAR(128), PRIMARY KEY (id) ); QUERY; /* クエリ内容がSELECT以外か判定 */ if (DB::isManip($query)){ return false; } /* クエリ実行 */ $result = $objdb->query($query); if (DB::isError($result)){ return false; } return $objdb->affectedRows(); } function execute() { $objdb =& RSL_db::getInstance(); /* 行の挿入内容 */ $acclist = array ( array (1,'tanaka','tanaka@mail.com'), array (2,'hujiy','hujiy@mail.com'), array (3,'takahashi','takahashi@mail.com') ); /* クエリーフォーマット */ $query = "INSERT INTO account_tbl VALUES(?,?,?) "; $sth = $objdb->prepare($sql); $result = $objdb->query($query); /* 同じフォーマットのクエリーを連続して行う */ foreach ($acclist as $values){ if (DB::isError($result = $objdb->execute($sth, $values))){ return false; } } // foreach ($acclist as $values) return $objdb->affectedRows(); }
SELECT処理
私は、データの取得にDB_Resultオブジェクトはあまり使いません。大抵は例に挙げた関数でデータを取得しています。
データの取得形式を選択できます。
・DB_FETCHMODE_ORDERED
配列による受け渡し
$row[0]
・DB_FETCHMODE_ASSOC連想配列による受け渡し
$row['id']
・DB_FETCHMODE_OBJECTオブジェクトによる受け渡し
$row->id
require_once ('DB.php'); require_once ('rsl_db.php'); function get_one() { $objdb =& RSL_db::getInstance(); /* データの取得 */ $query = "SELECT name FROM account_tbl LIMIT 1"; $result = $objdb->getOne($query); if (DB::isError($result)){ return false; } /* 1項目分の出力 */ echo $result; return true; } function get_row() { $objdb =& RSL_db::getInstance(); /* 一行のデータの取得 */ $query = "SELECT * FROM account_tbl LIMIT 1"; $result = $objdb->getRow($query,DB_FETCHMODE_ASSOC); if (DB::isError($result)){ return false; } /* 一行分の出力 */ echo $result['id']; echo $result['name']; echo $result['email']; } function get_all() { $objdb =& RSL_db::getInstance(); /* 全データの取得 */ $query = "SELECT * FROM account_tbl"; $result = $objdb->getAll($query,DB_FETCHMODE_ASSOC); if (DB::isError($result)){ return false; } /* 全データの出力 */ foreach ($result as $row=> $cols){ echo $cols['id']; echo $cols['name']; echo $cols['email']; } return true; }
-------------------- get_oneの結果 --------------------
tanaka
-------------------- get_rowの結果 --------------------
1 tanaka tanaka@mail.com
-------------------- get_allの結果 --------------------
1 tanaka tanaka@mail.com
2 hujiy hujiy@mail.com
3 takahashi takahashi@mail.com
その他
シーケンスをPEAR DBが自動で作ってくれます。各DBによって様々に動作しますがとっても便利な機能です。
$objdb->nextId('account');
(SQLiteはテーブルとトリガーでやり繰りしています)SQLite,MySQL,PostgreSQLではSELECTに含まれているLIMITを行ってくれます。
$objdb->limitQuery($query, $from, $count);
DB_Resultオブジェクトはこの時ぐらいしか使わないです。
昔、Oracleでうまく動作しなかった覚えがあります。
require_once ('DB.php'); require_once ('rsl_db.php'); function next_id() { $objdb =& RSL_db::getInstance(); $id = $objdb->nextId('account'); /* IDシーケンス */ /* 行の挿入 */ $query = "INSERT INTO account_tbl VALUES ({$id},'yujiro','yujiro@mail.net') "; $result = $objdb->query($query); if (DB::isError($result)){ return false; } return $objdb->affectedRows(); } function limit_query() { $objdb =& RSL_db::getInstance(); $from = 3; $count = 4; /* 範囲内のデータを取得 */ $query = "SELECT * FROM account_tbl"; $objres = $objdb->limitQuery($query, $from, $count); if (DB::isError($objres)){ return false; } while ($rows = $objres->fetchRow()) { foreach ($rows as $col=> $value){ echo = $value; } } // while ($rows = $objres->fetchRow()) return true; }
-------------------- limit_queryの結果 --------------------
3 takahashi takahashi@mail.com
4 maeda maeda@mail.com
5 iyda iyda@mail.com
6 yamadera yamadera@mail.com
