▶ プログラム関連
DBアクセスクラス - dfwLib2
DBアクセスクラス
DBにアクセスするためのPDOラッパークラスを提供しています。
require_once することで DBクラス が使用できます。
require_once(dirname(__FILE__).'/../lib/DB.class.php');
require_once('DB.class.php');
DB接続先指定
$GLOBALS['dfw']['db']['default'] = array(
'dsn' => 'mysql:dbname=XXXXX;host=localhost;charset=utf8',
'user' => 'tateno',
'pass' => 'system',
'hosts_match' => array(
'xxxxxxx' => array('dsn' => 'mysql:dbname=XXXXX;host=xxxxxx;charset=utf8', 'user' => 'hoge', 'pass' => 'taro'),
'develop' => array('dsn' => 'mysql:dbname=XXXXX;host=xxxxxx;charset=utf8'),
),
'names_match' => array(
'xxxxxxx' => array('dsn' => 'mysql:dbname=XXXXX;host=xxxxxx;charset=utf8', 'user' => 'hoge', 'pass' => 'taro'),
'develop' => array('dsn' => 'mysql:dbname=XXXXX;host=xxxxxx;charset=utf8'),
),
);
'hosts_match' は ホスト名 $_SERVER['HTTP_HOST'] に「キー」が含まれていた場合(部分一致)、使用する DSN、ID、PASS を切り替えます(オンライン向け)。
'names_match' は __サーバ名 php_uname('n')__ に「キー」が含まれていた場合(部分一致)、使用する DSN、ID、PASS を切り替えます(バッチプログラム向け)。
'hosts_match'、'names_match' はオプションです。
初期化(シングルトン)
設定情報(array)を渡して初期化します。
$db = DB::init(); // $GLOBALS['dfw']['db']['default'] 設定を使用します
$db = DB::init('master'); // $GLOBALS['dfw']['db']['master'] 設定を使用します
シングルトンを使用しない場合は、以下のように new を用いてオブジェクトを生成します。
$db = new DB('slave');
DBクローズ(コネクション切断)
明示的に接続名を指定してクローズします。
$db->close(); // $GLOBALS['dfw']['db']['default'] 設定コネクションをクローズします
$db->close('master'); // $GLOBALS['dfw']['db']['master'] 設定コネクションをクローズします
SQL実行の流れ
- (1) SQL定義
$db->setSql('SELECT * FROM memo WHERE name=:name AND flag=:flag');
- (2-1) SQLパラメータ設定(通常のやり方)
$db->set('name', 'tatenosystem');
$db->set('flag', 1);
- (2-2) SQLパラメータ設定(連想配列で一度に設定)
$params = array();
$params['name'] ='tatenosystem';
$params['flag'] = 1;
$db->sets( $params );
- (2-3) SQL INコマンド(INに設定する場合)
$db->setSql('SELECT * FROM memo WHERE name IN (:names)');
$db->setIn( 'names', array('tatenosystem', 'mahata', 'hoge') ); // IN の場合は setIn メソッド。配列を設定
- (3-1)SQL実行(1レコード取得)
$item = $db->execFetchOne();
var_dump( $item );
- (3-2) SQL実行(全レコード取得)
$items = $db->execFetchAll();
var_dump( $items );
簡単な使い方
-SELECT
$db->setSql('SELECT * FROM memo WHERE name = :name OR id = :id');
$db->set('name', 'tatenosystem');
$db->set('id', 35);
$data = $db->execFetchAll(); // 戻り値は全レコード
-UPADTE
$db->setSql('UPDATE memo SET name = :name WHERE id = :id');
$db->set('name', 'tatenosystem');
$db->set('id', 35);
$rtn = $db->exec(); // exec() の戻り値は更新レコード件数
-INSERT
$db->setSql('INSERT INTO memo (name, age) VALUES (:name, :age)');
$db->set('name', 'baby');
$db->set('age', 2);
$rtn = $db->exec(); // exec() の戻り値は更新レコード件数
-INSERT(メソッド使用)
$params = array('name' => 'baby', 'age' => 2);
$rtn = $db->insert('table_name', $params); // insert() の戻り値は更新レコード件数
-REPLACE(メソッド使用)
$params = array('name' => 'baby', 'age' => 2);
$rtn = $db->replace('table_name', $params); // replace() の戻り値は更新レコード件数
すこし凝った使い方
-SELECT実行(1レコードずつ取得)
$db->exec();
while( true ) {
$item = $db->fetch();
if( empty($item) ) break; // 取得終了時は空配列となる
var_dump( $item );
}
-SELECT実行(10レコードずつ取得)
$db->exec();
while( true ) {
$item = $db->fetchNum( 10 );
if( empty($item) ) break; // 取得終了時は空配列となる
var_dump( $item );
}
便利なINSERTメソッド
INSERT命令はSQL文を書かずに実行できるメソッドがあります。
戻り値は更新行数(成功時は1)となります。
$db = new DB();
$params = array( 'title'=>'ほげタイトル', 'description'=>'ほげんほげん' );
$ret = $db->insert( 'my_table', $params ); // INSERT実行
上記実行のSQLは、
INSERT INTO my_table ( title, description ) VALUES ( "ほげタイトル", "ほげんほげん" );
となります。
NOW()関数が使えます。
$db = new DB();
$params = array( 'title'=>'ほげタイトル', 'created_at'=>'NOW()' );
$ret = $db->insert( 'my_table', $params ); // INSERT実行
上記実行のSQLは、
INSERT INTO my_table ( title, created_at ) VALUES ( "ほげタイトル", NOW() );
となります。
同様のやり方で REPLACE も使用できます。
$ret = $db->replace( 'my_table', $params ); // REPLACE実行
2つのエラーハンドリングモード
try-catch (デフォルト)
try-catch でエラーハンドリングを行います。
try {
$db = DB::init($config);
$db->setSql('SELECT * FROM ROD_BOOKS WHERE ID IN (:hoge)');
$db->setIn('hoge', array(56,57,58,59,60,41));
$db->exec();
} catch (PDOException $e) {
var_dump($e->getMessage());
}
- PHP5 以降であれば set_exception_handler が使用できます。
function exception_handler($e) {
var_dump($e->getMessage());
}
set_exception_handler('exception_handler');
$db = DB::init($config);
$db->setSql('SELECT * FROM ROD_BOOKS WHERE ID IN (:hoge)');
$db->setIn('hoge', array(56,57,58,59,60,41));
$db->exec();
// 明示的な例外発生
throw new Exception('HogeHoge_Error');
メソッドの戻り値でエラーハンドリング
下記設定を行うとメソッドの戻り値でエラーハンドリングが行えます(ver1.0と同様)
$GLOBALS['dfw']['db']['trymode'] = false;
DBメソッドエラー時は false(boolean) が返却されます。
$rtn = $db->exec();
if ($rtn === false) {
echo 'DB execエラー';
var_dump($db->getErrorMessage());
}
コンストラクタのエラーチェックのみ isConnect メソッドを使用します。
isConnect メソッドは「メソッド戻り値エラーハンドリング」専用です。
$db = DB::init();
if ( ! $db->isConnect() ) {
echo 'DBコネクトエラー'
var_dump($db->getErrorMessage());
}
以下のメソッドのエラー時は false(boolean) が返却されます。
- exec()
- fetch()
- fetchAll()
- execFetchAll()
- execFetchOne()
- insert()
- multiInsert()
以下のエラー内容取得メソッドは「メソッド戻り値エラーハンドリング」専用です。
- getPdoException()
- getErrorMessage()
- getErrorCode()
トランザクション機能
※トランザクション非対応DBMSでは使用できません
- トランザクションの開始
$rtn = $db->beginTransaction();
成功した場合に true を、失敗した場合に false を返します。
- コミット
$rtn = $db->commit();
成功した場合に true を、失敗した場合に false を返します。
- ロールバック
$rtn = $db->rollBack();
成功した場合に true を、失敗した場合に false を返します。
その他の機能
マルチINSERT
$params = array(
array('column1' => 'value1', 'column2' => 'value2','column3' => 'value3'),
array('column1' => 'value1', 'column2' => 'value2','column3' => 'value3'),
array('column1' => 'value1', 'column2' => 'value2','column3' => 'value3'),
);
$rtn = $db->multiInsert('table_naame', $params);
※マルチINSERT対応DBMSのみ動作
※マルチINSERTを使用する際は、使用しているDBMSのマルチINSERT機能をよく理解してから使用してください
マルチREPLACE
マルチINSERTと同様
$rtn = $db->multiReplace('table_naame', $params);
※マルチREPLACE対応DBMSのみ動作
※マルチREPLACEを使用する際は、使用しているDBMSのマルチREPLACE機能をよく理解してから使用してください
最終行の取得(最終INSERT id の取得)
$id = $db->lastInsertId();
※PDO lastInsertId()のラッパー関数
その他 Tips
SQL処理がエラーになる
実際に実行されているSQL文を getSql メソッドで表示させて、問題がないか確認してください。
- try-catch の場合
try {
$db = DB::init($config);
$db->setSql('SELECT * FROM ROD_BOOKS WHERE ID IN (:hoge)');
$db->setIn('hoge', array(56,57,58,59,60,41));
$db->exec();
} catch (PDOException $e) {
var_dump($db->getSql()); // 実行に失敗したSQL文の表示
}
- メソッド戻り値エラーハンドリングの場合
$db = DB::init($config);
$db->setSql('SELECT * FROM ROD_BOOKS WHERE ID IN (:hoge)');
$db->setIn('hoge', array(56,57,58,59,60,41));
$rtn = $db->exec();
if ($rtn === false) {
var_dump($db->getSql()); // 実行に失敗したSQL文の表示
}
insert/replace メソッドでの現在時刻設定
MySQLでの現在時刻SQL関数 NOW() を使用できます。
$paramas = array(
'name' => 'hogehoge',
'createad_at' => 'NOW()',
);
insert('table_name', $params);
デフォルト値の NOW() 以外を使用する場合は、setNowSqlFunction メソッドでSQL関数名を指定してください(MySQL以外を使用している場合)。
$db->setNowSqlFunction( 'clock_timestamp()' );
PDO オブジェクトの取得
getPdo メソッドを使用します。
$pdoObject = $db->getPdo();
echo $db->getPdo()->getAttribute(PDO::ATTR_TIMEOUT);
セキュリティについて
SQL文生成で変数を利用すると「SQLインジェクション」が発生する恐れがあります。
$db->setSql('SELECT * FROM hoge WHERE id='.$_GET['id']); // 【危険】「SQLインジェクション」発生!
$db->setSql('SELECT * FROM hoge WHERE id='.$id); // 【危険】「SQLインジェクション」発生の恐れ!
$db->setSql('SELECT * FROM hoge WHERE id=:id); // 正しいSQL設定
$db->set('id', $_GET['id']); // $_GET['id']はバリデーション処理済みであること