<?php
class xser_dbo_mysql_sqlbuilder extends xser_dbo_sqlbuilder {
private $db_link_identifier ;
static function instance($db_link_identifier){
if (!is_resource($db_link_identifier))
throw new Exception('INVALID db_link_identifier');
static $instance;
if (is_null($instance))
$instance = new xser_dbo_mysql_sqlbuilder();
$instance->db_link_identifier = $db_link_identifier ;
return $instance;
}
public function escape_value($value){
if (is_int($value) || is_float($value)) { return $value; }
if (is_bool($value)) { return $value ? 1 : 0; }
if (is_null($value)) { return 'NULL'; }
return "'" . mysql_real_escape_string($value, $this->db_link_identifier) . "'";
}
public function sql_limit($length,$offset = null){
$sql = '' ;
if ( !empty($offset) ){
$sql = sprintf(' limit %d , %d',
(int)$offset ,empty($length) ? (int)$length : 4294967294) ;
} else if (!empty($length)){
$sql = " limit " . (int)$length;
}
return $sql ;
}
}
// 简单的通用sql生成器
abstract class xser_dbo_sqlbuilder {
// insert into table_name (f1,f2[,..]) values(v1,v2[,..])
const tpl_sql_insert = 'insert into %s (%s) values(%s)' ;
// select f1,f2[,..] from table_name [sql_conditions][sql_sort] [sql_limit]
const tpl_sql_select = 'select %s from %s %s %s %s' ;
// update table_name set pair1,pair2 [sql_conditions]
const tpl_sql_update = 'update %s set %s %s' ;
protected $meta_table = array();
public abstract function escape_value($value);
public abstract function sql_limit($length,$offset = null);
/**
* 重新初始化表元信息
* @param array $meta_table 表元信息
* @return xser_dbo_sqlbuilder
*/
public function table($meta_table){
$this->meta_table = $meta_table ;return $this ;
}
public function sql_insert($record){
if (xser::varify_provider()->not_null_array($record)){
$_row = array_map(array(& $this,'escape_value'),$record);
$columns = implode(',',array_keys($_row)) ;
$values = implode(',',array_values($_row)) ;
return sprintf(self::tpl_sql_insert,
$this->meta_table['table'],$columns,$values);
}
return '' ;
}
public function sql_update($record,$conditions=null){
if (!empty($record) && is_array($record)){
$_row = array_map(array(& $this,'escape_value'),$record);
$sql_conditions = empty($conditions)? '' : $this->sql_conditions($conditions);
$pairs = array();
foreach ($_row as $field=>$val){
$pairs[] = "{$field}={$val}" ;
}
$pairs = implode(',',$pairs) ;
return sprintf(self::tpl_sql_update,
$this->meta_table['table'],$pairs,$sql_conditions);
}
return '' ;
}
public function sql_select($conditions = null, $sort = null, $limit = null, $fields = '*'){
// 处理排序
$sql_sort = $sort != '' ? " order by {$sort}" : '';
if (is_array($limit)) {
list($length, $offset) = $limit;
} else {
$length = $limit;$offset = null;
}
$sql_limit = empty($length)? '' : $this->sql_limit($length,$offset);
$sql_conditions = empty($conditions)? '' : $this->sql_conditions($conditions);
return sprintf(self::tpl_sql_select,
$fields ,$this->meta_table['table'] ,$sql_conditions,$sql_sort,$sql_limit );
}
public function sql_conditions($conditions = null){
if (empty($conditions)) return '' ;
$sql = ' where ';
if (is_string($conditions) )
return $sql . $conditions ;
else if (is_array($conditions)){
$join_char = '' ;// 第一个条件前面 没有 and 连接符
foreach ($conditions as $field=>$cond){
// 支持 like / or 等操作 例如: 'name' => array('%Bob%','like')
$op_char = '=' ;
if (is_array($cond)){
$value = array_shift($cond);
// if $value is array , will use "in" [] opchar
if (is_array($value)){
$value = array_map(array(& $this,'escape_value'),$value);
$value = '[' . implode(',',$value) . ']' ;
}
$_op_char = array_shift($cond);
if (!empty($_op_char) && is_string($_op_char))
$op_char = $_op_char ;
}else {
$value = $cond ;
}
// 过滤值
$value = $this->escape_value($value);
$sql .= "{$join_char} {$field} {$op_char} {$value} " ;
$join_char = ' and ' ;
}
return $sql ;
}
return '' ;
}
}
demo如下:
<?php
class xser_rbac_table {
// 表
protected $table = null ;
protected $pk = null ;
//当前表为主表,及当前表主键在子表中的外键字段
protected $link = null ;
protected $link_fk = null ;
//当前表为子表,及当前表主键在主表中的外键字段
protected $belong = null ;
protected $belong_fk = null ;
//多对多
protected $more_to_more = null ;
protected $meta_table = null ;
function create($row,$msg=null,$affected_rows=0){
$this->_before_create($row);
$sql = $this->sqlbuilder()->sql_insert($row);
xser::dbo_provider()->execute($sql,$msg,$affected_rows);
return $affected_rows > 0 ;
}
function update($row,$conditions=null,$msg=null,$affected_rows=0){
$sql = $this->sqlbuilder()->sql_update($row,$conditions);
xser::dbo_provider()->execute($sql,$msg,$affected_rows);
return $affected_rows > 0 ;
}
function find_one($conditions=null, $fields = '*',$msg=null){
$sql = $this->sqlbuilder()->sql_select($conditions,null,1,$fields);
return xser::dbo_provider()->find_one($sql,$msg);
}
// 1:more , 仅仅支持单主键
function more_links($current,$fields = '*',$msg=null){
$sql = "select {$fields} from {$this->link}" ;
$conditions = array($this->link_fk => $current[$this->pk]);
$sql .= $this->sqlbuilder()->sql_conditions($conditions);
return xser::dbo_provider()->find_all($sql,$msg);
}
// 1:one , 仅仅支持单主键
function one_link($current,$fields = '*',$msg=null){
$sql = "select {$fields} from {$this->link}" ;
$conditions = array($this->link_fk => $current[$this->pk]);
$sql .= $this->sqlbuilder()->sql_conditions($conditions);
return xser::dbo_provider()->find_one($sql,$msg);
}
// 定位,当前对象从属于哪个对象
function belongs_to($current,$fields = '*',$msg=null){
$sql = "select {$fields} from {$this->belong}" ;
$conditions = array($this->belong_fk => $current[$this->pk]);
$sql .= $this->sqlbuilder()->sql_conditions($conditions);
return xser::dbo_provider()->find_one($sql,$msg);
}
function find_more($conditions=null, $fields = '*',$msg=null){
$sql = $this->sqlbuilder()->sql_select($conditions,null,null,$fields);
return xser::dbo_provider()->find_all($sql,$msg);
}
function _before_create(&$row){}
/**
* @return xser_dbo_sqlbuilder
*/
protected function sqlbuilder($table){
if (empty($this->meta_table))
$this->meta_table = array(
'table' => $this->table ,
'pk' => $this->pk ,
'fields' => xser::dbo_provider()->table_columns($this->table)
);
return xser::dbo_provider()->sqlbuilder()->table($this->meta_table);
}
}