PDOを利用したDBアクセスクラス2(自作ですけども)

以前との改良点
1. DB接続の設定をiniファイルからdefineに変更
2. dboクラスは拡張拡張可能になった。
phpのinclude_path設定に存在するディレクトリの中のDBOディレクトリ以下にあるファイルを検索する
ファイルの命名規則はクラス名と同じファイル名+拡張子がphpであること
3. 検索フィールド名のデミリタが変更可能


使用例:

$table_name = 't_foobar'; //DBに存在するテーブル名 or 拡張クラス名

//テーブルをコントロールするDBOクラスを取得する
$dbo = pdbo::Factory($table_name);

//検索
$condition = array(
 'foobar_name->eq' => 'foobar',
 'foobar_year' => 10,
);
$rows = $dbo->getAllBySearch( $condition ); //検索結果が配列で取得できる

クラス定義:

//検索フィールド名のデミリタ
define( 'PDBO_DEMILT', '->' );

//PDBの接続設定
define('PDO_DSN_STRING','');
define('PDO_DSN_USERNAME','');
define('PDO_DSN_PASSWORD','');

// PDOを利用したデータベースクラス
class pdbo{
	private static	$pdo;

	private function __construct(){
	}

	public function Factory( $table ){
		if( is_null( pdbo::$pdo ) ){
			try{
				pdbo::$pdo = new PDO(
					PDBO_DSN_STRING,
					DBO_DSN_USERNAME,
					DBO_DSN_PASSWORD,
					array(PDO::MYSQL_ATTR_INIT_COMMAND => "SET NAMES utf8")
			   	);
			} catch( PDOException $e ){
				echo $e->GetMessage();
				throw new Exception( $e->getMessage() );
			}
		}
		$tmp = explode(':', get_include_path() );
		foreach( $tmp as $val ){
			$tmp = "{$val}/DBO/{$table}.php";
			if( file_exists($tmp) ){
				include_once $tmp;
				return new $table( pdbo::$pdo, '', '' );
			}
		}
		return new pdbo_if( pdbo::$pdo, '', $table );
	}

}

class dbo{
	protected $dbo;
	protected $db_name;
	protected $table_name;
	protected $fields;
	protected $error_message;
	protected $query_log = array();

	public function __construct( &$pdbo, $db, $table ){
		$this->dbo		= $pdbo;
		$this->db_name	= $db;
		$this->table_name	= $table;
		if( strlen($this->table_name) == 0 ){
			$this->table_name = $this->_tablename;
			$table = $this->_tablename;
		}

		//テーブル情報取得
		try{
			$ret = $pdbo->query( 'DESCRIBE '.$table );
		} catch( PDOException $e ){
			$this->error_message = $e->getMessage();
			throw new Exception( $this->error_message );
		}
		$tmp = $ret->fetchAll( PDO::FETCH_ASSOC );
		if( !$tmp ) echo $table;
		foreach( $tmp as $node ){
			$type = $this->getType( $node['Type'] );
			$this->fields[$node['Field']]['type']= $type['type'];
			$this->fields[$node['Field']]['size']= $type['size'];
			$this->fields[$node['Field']]['option']= $type['option'];
			$this->fields[$node['Field']]['null']= $node['Null'];
			$this->fields[$node['Field']]['key']	= $node['Key'];
		}
	}

	public function pdbo_if( &$pdo, $db, $table){
		$this->__construct( $pdo, $db, $table );
	}

	public function DumpQuery(){
		print_r( $this->query_log );
	}

	public function TraceDump(){ return $this->DumpQuery(); }

	public function begin(){
		$this->dbo->beginTransaction();
	}

	public function commit(){
		$this->dbo->commit();
	}

	public function rollback(){
		$this->dbo->rollback();
	}

	public function getLastInsertID(){
		return $this->dbo->lastInsertId();
	}

	/**
	 * 一行だけレコードを取得する
	 *  $flagがtrueの時、条件配列にプライマリキーが存在しない場合エラーに
	 *  なります
	 * @param	array	$condition	条件配列
	 * @param	array	$sort	ソート配列
	 * @param	bool	$flag		プライマリキー存在チェック
	 * @param	array	$option	オプション
	 */
	public function getOnce(
	   	$condition, $order = array(), $flag = true, $option = array()
   	){
		$table	= $this->table_name;
		$dbo	=& $this->dbo;
		if( $flag ){
			//プライマリーキーの存在チェック
			$primary = $this->getPrimary();
			$keys = array_keys( $condition );
			foreach( $primary as $name  ){
				if( !in_array( $name, $keys ) ){
					throw new Exception('プライマリーキーが設定されていません');
				}
			}
		}

		//フィールド
		$fields = array();
		if( isset( $option['fields'] ) ) $fields = $option['fields'];
		//フィールド構築
		if( count( $fields ) ){
			$fields = $this->makefields( $fields );
			$fields = implode( ',', $fields );
		} else {
			$fields = '*';
		}

		//検索条件生成
		$ret = null;
		try{
			$where = $this->makeWhere( $condition );
			$_order = $this->makeOrder( $order );
			$_groupby= '';
			if( isset( $option['groupby'] ) && count( $option['groupby'] ) ){
				$_groupby = ' GROUP BY '.join( ',', $option['groupby'] );
			}

			$sql = "SELECT {$fields} FROM {$table}";
			if( strlen( $where ) > 0 ) $sql .= $where;
			if( strlen( $_order) > 0 ) $sql .= $_order;
			if( strlen( $_groupby) > 0 ) $sql .= $_groupby;

			$this->query_log[] = $sql;
			$ret = $dbo->query( $sql );

		} catch( PDOException $e ){
			$this->error_message = $e->getMessage();
			throw new Exception( $this->error_message );
		}

		//エラー処理
		if( $ret === false ) throw new Exception( "query error: {$sql}");

		//複数行検出
		if( $ret->rowCount() != 1 ) return false;

		return $ret->fetch(PDO::FETCH_ASSOC);
	}

	/**
	 *
	 */
	public function getRowBySearch(
		$condition, $order = array(), $flag = true, $option = array()
	){
		return $this->getOnce( $condition, $order, $flag, $option );
	}

	public function getRow(
		$condition, $order = array(), $flag = true, $option = array()
   	){
		return $this->getOnce( $condition, $order, $flag, $option );
	}

	/**
	 * 条件に一致するレコードを全て取得する
	 *  $flagがtrueの時、条件配列にプライマリキーが存在しない場合エラーに
	 *  なります
	 * @param	array	$condition	条件配列
	 * @param	bool	$flag		プライマリキー存在チェック
	 */
	public function getAllBySearch(
		$condition = array(), $order = array(), $option = array()
	){
		$table	= $this->table_name;
		$dbo	=& $this->dbo;

		//フィールド
		$fields = array();
		if( isset( $option['fields'] ) ) $fields = $option['fields'];
		//フィールド構築
		if( count( $fields ) ){
			$fields = $this->makefields( $fields );
			$fields = implode( ',', $fields );
		} else {
			$fields = '*';
		}

		//検索条件生成
		$ret = null;
		try{
			$where = $this->makeWhere( $condition );
			$_order = $this->makeOrder( $order );

			$sql = "SELECT {$fields} FROM {$table}";
			$sql .= $where;
			$sql .= $_order;
			$this->query_log[] = $sql;
			$ret = $dbo->query( $sql );

		} catch( PDOException $e ){
			$this->error_message = $e->getMessage();
			throw new Exception( $this->error_message );
		}

		//エラー処理
		if( $ret === false )  throw new Exception( "query error: {$sql}");

		return $ret->fetchAll(PDO::FETCH_ASSOC);
	}

	public function getAllBySearchWithPager(
		&$pager, $condition, $order=array(), $option=array()
	){

		unset($condition['limit'] );
		unset($condition['sort_number']);
		unset($condition['display_number']);
		if( isset($condition['from']) ) {
			$pager['now'] = $condition['from'] / $pager['limit'] + 1;
		}
		unset($condition['from']);
		unset($condition['numrows']);
		return $this->getAllPager( $condition, $order, $pager, $option );
	}
	/**
	 * 条件に一致するレコードを全て取得する
	 * また、ページャー情報を生成する
	 *  $flagがtrueの時、条件配列にプライマリキーが存在しない場合エラーに
	 *  なります
	 * @param	array	$condition	条件配列
	 * @param	bool	$flag		プライマリキー存在チェック
	 */
	public function getAllPager(
		$condition = array(), $order = array(), &$page, $option = array()
   	){
		$table	= $this->table_name;
		$dbo	=& $this->dbo;

		//フィールド
		$fields = array();
		if( isset( $option['fields'] ) ) $fields = $option['fields'];
		//フィールド構築
		if( count( $fields ) ){
			$fields = $this->makefields( $fields );
			$fields = implode( ',', $fields );
		} else {
			$fields = '*';
		}

		//検索条件生成
		$res = null;
		try{
			$where = $this->makeWhere( $condition );
			$_order = $this->makeOrder( $order );

			$sql = "SELECT {$fields} FROM {$table}";
			$sql .= $where;
			$sql .= $_order;
			$this->query_log[] = $sql;
			$res = $dbo->query( $sql );
			/*
			$res = $dbo->prepare(
				$sql, array(PDO::ATTR_CURSOR=>PDO::CURSOR_SCROLL)
			);
			 */
			$res->execute();

		} catch( PDOException $e ){
			$this->error_message = $e->getMessage();
			throw new Exception( $this->error_message );
		}

		//エラー処理
		if( $res === false )  throw new Exception( "query error: {$sql}");

		// ページャ処理
		if( !isset( $page['now'] ) ) {
			if( isset( $page['from'] ) ){
				if( $page['from'] == 0 ) $page['now'] = 1;
				else $page['now'] = ceil( $page['from'] / $page['limit'] );
			} else  {
			   	$page['now'] = 1;
			}
		}
		$page['rowCount'] = $res->rowCount();
		$page['pageMax'] = ceil( $page['rowCount'] / $page['limit'] );

		$page['start']	= ( $page['now'] - 1 ) * $page['limit'];
		if( $page['start'] < 1 ) $page['start'] = 0; 		$page['end'] = $page['now'] * $page['limit']; 		if( $page['end'] > $page['rowCount'] ) $page['end'] = $page['rowCount'];

		// レコード取得
		$ret = array();
		$all = $res->fetchAll(PDO::FETCH_ASSOC);
		if( $page['rowCount'] > 0 ){
			for( $n = $page['start']; $n < $page['end']; $n ++ ){
				if( !isset($all[$n]) ) break;
				$ret[] = $all[$n];
				/*
				echo "n: {$n}
$n";
				$tmp = $res->fetch( PDO::FETCH_ASSOC, PDO::FETCH_ORI_ABS, $n );
				if(!$tmp) break;
				 $ret[] = $tmp;
				 */
			}
		}

		return $ret;
	}

	/**
	 * ページャ情報を編集する
	 */
	public function fixPager( $pager, $option = array() ){
		/*
		 * numrows
		 * allnumrows
		 * to
		 * firstpage
		 * prev
		 * pages
		 * next
		 * lastpage
		 */
		$tmp = $pager;
		$pager = array(
			'numrows'	=> $tmp['rowCount'],
			'allnumrows'=> $tmp['rowCount'],
			'from'		=> $tmp['start'] + 1,
			'to'		=> $tmp['end'],
			'firstpage'	=> '',
			'prev'		=> '',
			'next'		=> '',
			'lastpage'	=> '',
			'pages'		=> array(),
			'current'	=> $tmp['now'],
		);
		//リンク生成
		$myFile = basename( $_SERVER['SCRIPT_NAME'] );

		$opt = '';
		if( count($option) ) {
			$tt = array();
			foreach( $option as $key => $val) $tt[] = "{$key}={$val}";
			$opt = '&'.implode('&',$tt);
		}

		if( $tmp['pageMax'] == 1 ){
			$pager['firstpage'] = null;
			$pager['prev'] = null;
		}
		if( $tmp['pageMax'] == $tmp['now'] || $tmp['pageMax'] == 1){
			$pager['next'] = null;
			$pager['lastpage'] = null;
		}

		for( $n = 1; $n  1 ){
			$pager['prev'] = $pager['pages'][$pager['current']-1];
			$pager['firstpage'] = $pager['pages'][1];
		}

		if( $tmp['pageMax'] > 1 && $pager['current'] < $tmp['pageMax']){ 			$pager['next'] = $pager['pages'][$pager['current']+1]; 			$pager['lastpage'] = $pager['pages'][$tmp['pageMax']]; 		} 		return $pager; 	} 	/** 	 * 唯一のレコード更新 	 */ 	public function updateOnce( $data ){ 		$now = time(); 		$table	= $this->table_name;
		$dbo	=& $this->dbo;
		$fields =& $this->fields;

		//更新データ
		$up_data = array();
		//条件データ
		$condition = array();
		foreach( $data as $name => $val ){
			//if( !in_array( $name, array_keys($fields) ) ) continue;
			list( $nm ) = $this->getfieldName( $name );
			if( $fields[$nm]['key'] == 'PRI' ){
				$condition[$name] = $val;
			} else {
				$up_data[$name] = $val;
			}
		}
		if( count($condition) == 0) {
			throw new Exception(
				"updateOnce関数の引数にプライマリキーがありませんでした。"
		   	);
		}

		//更新日
		if( array_key_exists( 'update_datetime', $this->fields ) &&
			!array_key_exists( 'update_datetime', $data  )
		){
			$data['update_datetime'] = $now;
		}

		return $this->update( $up_data, $condition );
	}

	/**
	 * 複数更新
	 */
	public function update( $data, $condition = array() ){
		$now = time();
		$table	= $this->table_name;
		$dbo	=& $this->dbo;
		$fields =& $this->fields;
		$node = array();

		//更新日
		if( array_key_exists( 'update_datetime', $this->fields ) &&
			!array_key_exists( 'update_datetime', $data )
		){
			$data['update_datetime'] = $now;
		}

		$upd_data = array();
		foreach( $data as $key => $val ) {
			if( !is_array( $val ) ) $val = addslashes( $val );
			$option = '';
			//オプション検出
			if( strpos( $key, PDBO_DEMILT )  !== false ){
				$tmp = $key;
				$tmp = explode( PDBO_DEMILT, $tmp );
				$key = $tmp[0];
				$option = $tmp[1];
				//存在しないキーはスキップ
				if( !array_key_exists( $key, $fields ) ) continue;

				if( !is_array( $val ) ){
					//文字列 日付型 の場合の処理
					if( $this->isString( $fields[$key]['type'] ) ||
						$this->isDate( $fields[$key]['type'] )
					) {
						$val = "'{$val}'";
					} else {
						//セカンドオプションがある時
						if( isset( $tmp[2] ) ){
							//セカンドオプションが文字型の時
							if( $tmp[2] == 'STR' ) $val = "'{$val}'";
						}
					}
				}

				$upd_data[$key] = $this->CombineValue( $key, $option, $val);
			} else {
				if( !array_key_exists( $key, $fields ) ) continue;

				//文字列 日付型 の場合の処理
				if( $this->isString( $fields[$key]['type'] ) ) $val="'{$val}'";
				if($this->isDate( $fields[$key]['type'] )
				) {
					$val = "'".date('Y-m-d H:i:s', $val)."'";
				} else {
					//セカンドオプションがある時
					if( isset( $tmp[2] ) ){
						//セカンドオプションが文字型の時
						if( $tmp[2] == 'STR' ) $val = "'{$val}'";
					}
				}
				$upd_data[$key] = $val;
			}
		}

		try{
			$where = $this->makeWhere( $condition );
			$node = array();
			foreach( $upd_data as $name => $val){
				$node[] = "{$name} = {$val}";
		   	}
			$sql = "UPDATE {$table} SET ".implode( ' , ', $node )." {$where}";
			$this->query_log[] = $sql;
			$dbo->query( $sql );
		} catch( Exception $e){
			echo $e->getMessage();
			return false;
		}
		return true;
	}

	/**
	 * 一行だけレコードを取得する
	 *  $flagがtrueの時、条件配列にプライマリキーが存在しない場合エラーに
	 *  なります
	 * @param	array	$data		登録情報
	 * @param	bool	$flag		プライマリキー存在チェック
	 */
	public function insert( $data, $flag = true ){
		$now = time();
		if( count( $data ) == 0 ) return false;

		$fields =& $this->fields;

		//登録日
		if( array_key_exists( 'regist_datetime', $this->fields ) &&
			!array_key_exists( 'regist_datetime', $data )
		){
			$data['regist_datetime'] = $now;
		}
		//更新日
		if( array_key_exists( 'update_datetime', $this->fields ) &&
			!array_key_exists( 'update_datetime', $data  )
		){
			$data['update_datetime'] = $now;
		}

		$tmp = $data;
/*
		//文字列次処理
		foreach( $data as $name => $val ){
			//文字列時にクォートをつける
			if( $this->isString($fields[$name]['type']) ){
				$val = "'".addslashes($val)."'";
			}
			//日付時にクォートをつける
			if( $this->isDate($fields[$name]['type']) ) {
				if( is_int( $val ) ){
					$val = date( 'Y-m-d H:i:s', $val );
				}
				$val = "'".addslashes($val)."'";
			}
			$data[$name] = $val;
		}
 */
		$inst_data = array();
		foreach( $data as $key => $val ) {
			if( !is_array( $val ) ) $val = addslashes( $val );
			$option = '';
			//オプション検出
			if( strpos( $key, PDBO_DEMILT )  !== false ){
				$tmp = $key;
				$tmp = explode( PDBO_DEMILT, $tmp );
				$key = $tmp[0];
				$option = $tmp[1];
				//存在しないキーはスキップ
				if( !array_key_exists( $key, $fields ) ) continue;

				if( !is_array( $val ) ){
					//文字列 日付型 の場合の処理
					if( $this->isString( $fields[$key]['type'] ) ||
						$this->isDate( $fields[$key]['type'] )
					) {
						$val = "'{$val}'";
					} else {
						//セカンドオプションがある時
						if( isset( $tmp[2] ) ){
							//セカンドオプションが文字型の時
							if( $tmp[2] == 'STR' ) $val = "'{$val}'";
						}
					}
				}
				$inst_data[$key] = $this->CombineValue( $key, $option, $val);
			} else {
				if( !array_key_exists( $key, $fields ) ) continue;

				//文字列 日付型 の場合の処理
				if( $this->isString( $fields[$key]['type'] ) ) $val="'{$val}'";
				if($this->isDate( $fields[$key]['type'] )
				) {
					$val = "'".date('Y-m-d H:i:s', $val)."'";
				} else {
					//セカンドオプションがある時
					if( isset( $tmp[2] ) ){
						//セカンドオプションが文字型の時
						if( $tmp[2] == 'STR' ) $val = "'{$val}'";
					}
				}
				$inst_data[$key] = $val;
			}
		}

		//インサートチェック
		if(($name=pdbo_if::existsfield($inst_data,$this->getNotNull()))!==true){
			throw new Exception(
				"{$name}はnot nullのフィールドですが、存在していませんでした。"
		   	);
		}

		$sql = "INSERT INTO {$this->table_name} ( ".
			implode( ' , ', array_keys($inst_data) )." ) VALUES ( ";
		$sql .= implode( ', ', $inst_data )." ); ";

		try{
			$this->query_log[] = $sql;
			$ret = $this->dbo->query( $sql );
		} catch( PDOException $e ) {
			throw new Exception( 'Insert Error:'.$e->getMessage() );
		}
		if( $ret === false ){
			throw new Exception( 'Insert Error: '.$sql );
		}
		return true;
	}

	/**
	 * 一件削除
	 */
	public function deleteOnce( $condition = array() ){
	}

	/**
	 * 条件削除
	 */
	public function deleteSearch( $condition ){
		//if( count( $condition ) == 0 ) return false;

		$sql = "DELETE FROM {$this->table_name} ".$this->makeWhere($condition);

		try{
			$this->query_log[] = $sql;
			$ret = $this->dbo->query( $sql );
		} catch( PDOException $e ) {
			throw new Exception( 'Insert Error:'.$e->getMessage() );
		}
		return true;
	}

	public function deleteByArray($ids){
		$condition = array();
		foreach( $ids as $key => $val ){
			$condition[$key.'->in'] = $val;
		}
		return $this->deleteSearch( $condition );
	}

	/**
	 * Where句の生成
	 */
	private function makeWhere( $condition ){
		if( count( $condition ) == 0 ) return '';
		$fields = $this->fields;
		$where = array();

		foreach( $condition as $key => $val ){
			if( !$val ) continue;
			if( is_string($val) && strlen( trim($val) ) == 0  ) continue;
			if( is_array($val) && count( $val ) == 0  ) continue;

			if( !is_array( $val ) ) $val = addslashes( $val );

			$option = '';
			//オプション検出
			if( strpos( $key, PDBO_DEMILT )  !== false ){
				//オプション取得
				$tmp = $key;
				$tmp = explode( PDBO_DEMILT, $tmp );
				$key = $tmp[0];
				$option = $tmp[1];

				//テーブルにカラムが存在するか
				if( !isset( $fields[$key] ) ){
					throw new Exception(
						"{$key}は{$this->table_name}に存在しないカラムです"
				   	);
				}

				if( !is_array( $val ) ){
					//文字列 日付型 の場合の処理
					if( $this->isString( $fields[$key]['type'] ) ||
						$this->isDate( $fields[$key]['type'] )
					) {
						$val = "'{$val}'";
					} else {
						//セカンドオプションがある時
						if( isset( $tmp[2] ) ){
							//セカンドオプションが文字型の時
							if( $tmp[2] == 'STR' ) $val = "'{$val}'";
						}
					}
				}

				$where[] = $this->CombineStr( $key, $option, $val );

			} else {
				//オプションが無いとき

				//テーブルにカラムが存在するか
				if( !isset( $this->fields[$key] ) ){
					throw new Exception(
						"{$key}は{$this->table_name}に存在しないカラムです"
				   	);
				}

				if( $this->isString($fields[$key]['type'] ) ) {
					$where[] = "{$key} LIKE '%{$val}%'";
				} else {
					$where[] = "{$key} = {$val}";
				}
			}
		}
		if( count( $where ) == 0 ) return '';
		return " WHERE ".implode( ' AND ', $where );
	}

	/**
	 * 配列からWhere文を生成する
	 */
	public function makeWhereArray( $condition ){
		if( count( $condition ) == 0 ) return '';
		$where = array();
		foreach( $condition as $key => $val ){
			if( is_string($val) && strlen( trim($val) ) == 0  ) continue;
			if( is_array($val) && count( $val ) == 0  ) continue;

			if( !is_array( $val ) ) $val = addslashes( $val );
			$option = '';
			//オプション検出
			if( strpos( $key, PDBO_DEMILT )  !== false ){
				//オプション取得
				$tmp = $key;
				$tmp = explode( PDBO_DEMILT, $tmp );
				$key = $tmp[0];
				$option = $tmp[1];

				//セカンドオプションがある時
				if( isset( $tmp[2] ) ){
					//セカンドオプションが文字型の時
					if( $tmp[2] == 'STR' ) $val = "'".$val."'";
				}

				$where[] = $this->CombineStr( $key, $option, $val );

			} else {
				//オプションが無いとき

				$where[] = "{$key} = {$val}";
			}
		}
		if( count( $where ) == 0 ) return '';
		return " WHERE ".implode( ' AND ', $where );
	}

	/**
	 * 配列からORDER文を生成する
	 */
	public function makeOrderArray( $order ){
		if( count( $order ) == 0 ) return '';

		$ret = array();
		$fields = $this->fields;
		$kyes = array_keys( $order );
		foreach( $order as $name => $val ){
			$ret[] = "{$name} {$val}";
		}
		if( count( $ret ) == 0 ) return '';
		return " ORDER BY ".implode( " , ", $ret );
	}

	/**
	 * フィールド生成
	 */
	protected function makefields( $fields ){
		$ret = array();
		foreach( $fields as  $val ){
			$val = addslashes( $val );
			//オプション検出
			if( strpos( $val, PDBO_DEMILT )  !== false ){
				//オプション取得
				$tmp = $val;
				$tmp = explode( PDBO_DEMILT, $tmp );
				$key = $tmp[0];
				$option = $tmp[1];

				$ret[] = $this->CombineField( $key, $option )."AS {$key}";

			} else {
				//オプションが無いとき

				$ret[] = $val;
			}
		}
		return $ret;
	}

	protected function CombineValue( $key, $option, $val ){
		$ret = '';
		switch( $option ){
			//暗号 復号化 
			case 'decrypt':
				$ret = "AES_DECRYPT('{$val}','".CRYPT_CODE."') ";
				break;

			//暗号 符号化
			case 'crypt':
				$ret = "AES_ENCRYPT('{$val}','".CRYPT_CODE."') ";
				break;

			//その他
			default:
				$ret = $val;
				break;
		}
		return $ret;
	}

	/**
	 * セレクトのフィールド生成
	 */
	protected function CombineField( $key, $option ){
		$ret = '';
		switch( $option ){
			case 'max':
				$ret = "MAX( {$key} )";
				break;

			//暗号 復号化 
			case 'decrypt':
				$ret = "AES_DECRYPT({$key},'".CRYPT_CODE."') ";
				break;

			//暗号 符号化
			case 'crypt':
				$ret = "AES_ENCRYPT({$key},'".CRYPT_CODE."') ";
				break;

			//その他
			default:
				$ret = $key;
				break;
		}
		return $ret;
	}

	/**
	 * オプションに対応したSQL構築
	 */
	protected function CombineStr( $key, $option, $val ){
		$ret = '';
		switch( $option ){
			case 'begin':
			case 'beginYMD':
			case 'from':
				$ret = "{$key} >= {$val}";
				break;
			case 'end':
			case 'endYMD':
			case 'to':
				$ret = "{$key}  {$val}";
				break;

			case 'lt':
				$ret = "{$key} < {$val}"; 				break; 			case '--': 				$ret = "{$key} {$val}"; 				break; 			case 'like': 				$ret = "{$key} LIKE {$val}"; 				break; 			case 'likebin': 				$ret = "{$key} LIKE BINARY {$val}"; 				break; 			case 'eq': 				$ret = "{$key} = {$val}"; 				break; 			case 'neq': 				$ret = "{$key} != {$val}"; 				break; 			case 'in': 				$ret = "{$key} IN (".implode(',', $val).")"; 				break; 			case 'not_in': 				$ret = "NOT ( {$key} IN (".implode(',', $val).") )"; 				break; 			case 'crypt': 				$ret = "AES_DECRYPT({$key},'".CRYPT_CODE."') ". 					" = {$val}"; 				break; 			case 'crypt_like': 				$ret = "AES_DECRYPT({$key},'".CRYPT_CODE."') ". 					"LIKE '%{$val}%'"; 				break; 			case 'crypt_likebin': 				$ret = "AES_DECRYPT({$key},'".CRYPT_CODE."') ". 					"LIKE BINARY '%{$val}%'"; 				break; 			default: 				throw  new Exception( 'makeWhere error: '. 					'指定されないオプションを検出しました' 			   	); 		} 		return $ret; 	} 	/** 	 * ソート文構築 	 */ 	protected function makeOrder( $order ){ 		if( count( $order ) == 0 ) return ''; 		$ret = array(); 		$fields = $this->fields;
		$kyes = array_keys( $order );
		//テーブルにカラムが存在するか
		foreach( $order as $name => $val ){
			if( !isset( $fields[$name] ) ){
				throw new Exception(
					"{$name}は{$this->table_name}に存在しないカラムです"
		   		);
			}
			$ret[] = "{$name} {$val}";
		}
		if( count( $ret ) == 0 ) return '';
		return " ORDER BY ".implode( " , ", $ret );
	}

	/**
	 * 文字型かを判別する
	 */
	protected function isString( $type ){
		switch( strtolower($type) ){
			case 'char':
			case 'varchar':
			case 'text':
			case 'longtext':
				return true;
		}
		return false;
	}

	/**
	 * 日付型かを判別する
	 */
	protected function isDate( $type ){
		switch( strtolower($type) ){
			case 'date':
			case 'datetime':
			case 'timestamp':
				return true;
		}
		return false;
	}

	/**
	 * Mysqlのカラムタイプから型とサイズ、オプション属性を切り離す
	 */
	private function getType( $type ){
		$ret = array(
			'size'	=> '',
			'type'	=> '',
			'option'=> '',
		);
		$st	= 0;
		$end= 0;
		$st = strpos( $type, '(' );
		if( $st === false ){
			$ret['type'] = $type;
			return $ret;
		}
		$ret['type'] = substr( $type, 0, $st );
		$end = strpos( $type, ')' );
		$ret['size'] = substr( $type, $st+1, $end-$st-1 );
		$tmp = explode( ' ', $type );
		if( count( $tmp ) > 1 ) $ret['option'] = $tmp[1];
		return $ret;
	}

	/**
	 * プライマリーキー配列の取得
	 */
	private function getPrimary(){
		$ret = array();
		foreach( $this->fields as $name => $node ){
			if( $node['key'] == 'PRI' ){
				$ret[] = $name;
			}
		}
		return $ret;
	}

	private function getNotNull(){
		$ret = array();
		foreach( $this->fields as $name => $node ){
			if( $node['null'] == 'No' ){
				$ret[] = $name;
			}
		}
		return $ret;
	}

	/**
	 * $list配列内のフィールドが$fieldsに含まれているかチェックする
	 */
	private function existsfield( $fields, $list ){
		$keys = array_keys( $fields );
		foreach( $list as $name ){
			if( !in_array( $name, $keys ) ) return $name;
		}
		return true;
	}

	/**
	 * フィールド名を取得
	 */
	private function getfieldName( $name ){
		if( strpos( $name, PDBO_DEMILT )  === false ) return array( $name, '' );
		return explode( PDBO_DEMILT, $name );
	}
}