分类:
2009-12-30 18:50:16
/**
* 数据访问层,仅处理MYSQL
* 包括
* by:李勇
* at:2009-01-19
*/
final class DalSplite{
public function __construct(PDO $pdo){
}
}
/**
* 指定库中的指定表的访问类
*
*/
final class DalTable{
private $pdo;
private $tableName;
private $meta;
private $primaryKey;
/**
* 构造方法
*
* @param PDO $pdo
* @param string $tableName
*/
public function __construct(PDO $pdo,$tableName){
if(!is_string($tableName)) return null;
$this->pdo=$pdo;
$this->tableName=$tableName;
$this->meta=false;
$this->primaryKey=false;
return $this;
}
/**
* 获取本表的表结构(元数据),失败时返回0
*
* @return 0/array:<列名>=>array(列信息)
*/
private function getMeta(){
if($this->meta!==false)return $this->meta;
$sql="DESCRIBE ".$this->tableName;
$table=$this->query($sql);
if(!$table or !count($table)){
$this->meta=0;
}else{
$meta=array();
foreach ($table as $col) {
$meta[$col['Field']]=$col;
}
$this->meta=$meta;
}
return $this->meta;
}
/**
* 获取本表的主键字段,无主键或组合主键时返回0
*
* @return 0/主键字段名
*/
private function getPrimaryKey(){
if($this->primaryKey!==false)return $this->primaryKey;
$sql="SHOW INDEX FROM ".$this->tableName;
$table=$this->query($sql);
if(!$table or !count($table)){
$this->primaryKey=0;
}else{
$pkvs=array();
foreach ($table as $row) {
if($row['Key_name']=='PRIMARY')$pkvs[]=$row['Column_name'];
}
if(count($pkvs)!=1){
$this->primaryKey=0;
}else{
$this->primaryKey=$pkvs[0];
}
}
return $this->primaryKey;
}
/**
* Enter description here...
*
* @param bool $distinct 是否消重
* @param mixed $fields 请参考createFields
* @param mixed $where 请参考createWhere
* @param mixed $groupby 请参考createGroupby
* @param mixed $having 请参考createHaving
* @param mixed $orderby 请参考createOrderby
* @param mixed $limit 请参考createLimit
* @return mixed 单值/一维无键数组/一维有键数组/二维数组(一维无键,二维有键)
*/
private function _select($distinct,$fields=null,$where=null,$groupby=null,$having=null,$orderby=null,$limit=null){
if(is_object($fields))$fields=get_object_vars($fields);
if(!$where and !$groupby and !$having and !$orderby and !$limit and is_array($fields) and isset($fields['fields'])){
if(isset($fields['where']))$where=$fields['where'];
if(isset($fields['groupby']))$groupby=$fields['groupby'];
if(isset($fields['having']))$having=$fields['having'];
if(isset($fields['orderby']))$orderby=$fields['orderby'];
if(isset($fields['limit']))$limit=$fields['limit'];
$fields=$fields['fields'];
return $this->_select($distinct,$fields,$where,$groupby,$having,$orderby,$limit);
}
$fields=$this->createFields($fields);
$where=$this->createWhere($where);
$groupby=$this->createGroupby($groupby);
$having=$this->createHaving($having);
$orderby=$this->createOrderby($orderby);
$limit=$this->createLimit($limit);
$sql='SELECT ';
if($distinct)$sql.='DISTINCT ';
$sql.=$fields;
$sql.=" FROM ".$this->tableName." ";
$sql.=$where.$groupby.$having.$orderby.$limit;
$set=$this->query($sql);
$rows=count($set);
if($rows)$cols=count($set[0]);
else $cols=0;
if($rows==1 and $cols==1){
$col=array();
foreach ($set[0] as $cell) {
$col[]=$cell;
}
return $col[0];
}
if($rows==1){
return $set[0];
}
if($cols==1){
$col=array();
foreach ($set as $row) {
$col[]=$row[0];
}
return $col;
}
return $set;
}
/**
* 返回查询结果
* 请参考_select
*/
public function select($fields=null,$where=null,$groupby=null,$having=null,$orderby=null,$limit=null){
return $this->_select(false,$fields,$where,$groupby,$having,$orderby,$limit);
}
/**
* 返回消重后的查询结果
* 请参考_select
*/
public function distinct($fields=null,$where=null,$groupby=null,$having=null,$orderby=null,$limit=null){
return $this->_select(true,$fields,$where,$groupby,$having,$orderby,$limit);
}
/**
* 插入一条数据
*
* @param array[1] $row
* <列名>=><值>
* @return int
*/
public function insert($row){
if(!$row)return false;
if(is_object($row))$row=get_object_vars($row);
if(!is_array($row))return false;
$meta=$this->getMeta();
$fields='';
$values='';
foreach ($row as $name=>$value){
if(!is_string($name))continue;
if(!isset($meta[$name]))continue;
if($fields)$fields.=' , ';
$fields.=$name;
if($values)$value.=' , ';
$values.="'".mysql_escape_string($value)."'";
}
if(!$fields or !$values)return false;
$sql="INSERT INTO ".$this->tableName.'('.$fields.') VALUES('.$values.')';
$count=$this->execute($sql);
if(!$count)return false;
return $this->pdo->lastInsertId();
}
/**
* 删除表中的部分数据
*
* @param mixed $where
* 请参考createWhere
* @return int
*/
public function delete($where){
$where=trim($this->createWhere($where));
if(!$where)return false;
$sql="DELETE FROM ".$this->tableName." ".$where;
return $this->execute($sql);
}
/**
* 删除表中全部数据
*
* @return int
*/
public function deleteAll(){
$sql="DELETE FROM ".$this->tableName;
return $this->execute($sql);
}
/**
* 修改表中的部分数据
*
* @param array[1] $row
* <列名>=><值>
* @param mixed $where
* 请参考createWhere
* @return int
*/
public function update($row,$where){
if(!$row)return false;
if(is_object($row))$row=get_object_vars($row);
if(!is_array($row))return false;
$meta=$this->getMeta();
$set='';
foreach ($row as $name=>$value){
if(!is_string($name))continue;
if(!isset($meta[$name]))continue;
if($set)$set.=' , ';
$set=$name."='".mysql_escape_string($value)."' ";
}
if(!$set)return false;
$where=$this->createWhere($where);
if(!$where)return false;
$sql="UPDATE ".$this->tableName." SET ".$set." ".$where;
return $this->execute($sql);
}
/**
* 生成字段列表
*
* @param mixed $fields
* null/''/0 所有字段
* string 直接使用
* object/array
* <列名|计算值>
* <列名|计算值>=><别名>
* @return string
*/
private function createFields($fields=null){
if(!$fields)return '*';
if(is_string($fields)) return trim($fields);
if(is_object($fields))$fields=get_object_vars($fields);
if(!is_array($fields)) return '*';
$ret='';
foreach($fields as $key=>$value){
if(is_int($key)){
if(!is_string($value))continue;
if($ret)$ret.=' , ';
$ret.=$value;
continue;
}
if(!is_string($value))continue;
if($ret)$ret.=' , ';
$ret.=$key.' AS '.$value;
}
return $ret;
}
/**
* 生成WHERE子句
*
* @param mixed $where
* 参考createCondition
* @return string
*/
private function createWhere($where){
$condition=$this->createCondition($where);
if(!$condition)return '';
$condition=trim($condition);
if(strpos(strtoupper($condition),'WHERE')===0)return $condition;
return 'WHERE '.$condition;
}
/**
* 生成HAVING子句
*
* @param mixed $having
* 参考createCondition
* @return string
*/
private function createHaving($having){
$condition=$this->createCondition($having);
if(!$condition)return '';
$condition=trim($condition);
if(strpos(strtoupper($condition),'HAVING')===0)return $condition;
return 'HAVING '.$condition;
}
/**
* 生成 GROUP BY 子句
*
* @param mixed $groupby
* 参考createSort
* @return string
*/
private function createGroupby($groupby){
$sort=$this->createSort($groupby);
if(!$sort)return '';
$sort=trim($sort);
if(strpos(strtoupper($sort),'GROUP')===0)return $sort;
return 'GROUP BY '.$sort;
}
/**
* 生成 ORDER BY 子句
*
* @param mixed $orderby
* 参考createSort
* @return string
*/
private function createOrderby($orderby=null){
$sort=$this->createSort($orderby);
if(!$sort)return '';
$sort=trim($sort);
if(strpos(strtoupper($sort),'ORDER')===0) return $sort;
return 'ORDER BY '.$sort;
}
/**
* 生成列排序子句,用于Order By与Group By中
*
* @param mixed $sort
* string 直接使用
* object/arrray
* <列名> ASC|asc|DESC|desc
* [<列名>|<列名>=>,...]
* @return string
*/
private function createSort($sort=null){
if(!$sort)return '';
if(is_string($sort)) return trim($sort);
if(is_object($sort))$sort=get_object_vars($sort);
if(!is_array($sort)) return '';
if(count($sort)==2 and (strtoupper($sort[1])=='ASC' or strtoupper($sort[1])=='DESC')) return $sort[0].' '.strtoupper($sort[1]);
$meta=$this->getMeta();
$ret='';
foreach ($sort as $key=>$value) {
if(is_int($key)){
if(!isset($meta[$value]))continue;
if($ret)$ret.=' , ';
$ret.=$value;
continue;
}
if(strtoupper($value)=='ASC' or strtoupper($value)=='DESC'){
if(!isset($meta[$key]))continue;
if($ret)$ret.=' , ';
$ret.=$key.' '.strtoupper($value);
continue;
}
continue;
}
return $ret;
}
/**
* 生成分页子句
*
* @param mixed $limit
* string 直接使用,其中可包含LIMIT
* int 只限制行数,不限制偏移
* object/array
* [limit/LIMIT/Limit=><行数>,Offset/offset/OFFSET=><偏移>]
* [<行数>,<偏移>]
* [<行数>]
* @return string
*/
private function createLimit($limit=null){
if(!$limit)return '';
if(is_string($limit)){
$limit=trim($limit);
if(strpos(strtoupper($limit),'LIMIT')===0) return strtoupper($limit);
return 'LIMIT '.$limit;
}
if(is_int($limit)) return 'LIMIT '.$limit;
if(is_object($limit))$limit=get_object_vars($limit);
if(!is_array($limit))return '';
$l=null;
$o=null;
if(isset($limit['Limit']))$l=$limit['Limit'];
if(isset($limit['limit']))$l=$limit['limit'];
if(isset($limit['LIMIT']))$l=$limit['LIMIT'];
if(isset($limit['Offset']))$o=$limit['Offset'];
if(isset($limit['offset']))$o=$limit['offset'];
if(isset($limit['OFFSET']))$o=$limit['OFFSET'];
if($l){
if($o){
return 'LIMIT '.$l.' OFFSET '.$o;
}
return 'LIMIT '.$l;
}
if(count($limit)==2){
$l=$limit[1];
$o=$limit[0];
return 'LIMIT '.$l.' OFFSET '.$o;
}
if(count($limit)==1) return 'LIMIT '.$limit[0];
return '';
}
/**
* 生成条件表达式,用于Where,Having子句中
*
* @param mixed $condition
* string 直接使用
* int 主键值
* object/array and组合
* PrimaryKey=>主键值
* 列名=>列值(string/int)
* @return string
*/
private function createCondition($condition=null){
if(is_null($condition)) return '';
if(is_string($condition)) return trim($condition);
if(is_int($condition)){
if($this->getPrimaryKey())
return $this->getPrimaryKey()."='".$condition."' ";
return '';
}
if(is_object($condition))$condition=get_object_vars($condition);
if(!is_array($condition))return '';
if(isset($condition['PrimaryKey'])){
if($this->getPrimaryKey())
return $this->getPrimaryKey()."='".mysql_escape_string($condition['PrimaryKey'])."'";
return '';
}
$meta=$this->getMeta();
$ret='';
foreach ($condition as $key=>$value) {
if(!is_int($key)){
if(!isset($meta[$key]))continue;
if(!is_int($value)&&!is_string($value))continue;
if(is_string($value))$value=trim($value);
if($ret)$ret.=' and ';
$ret.=' '.$key."='".mysql_escape_string($value)."' ";
continue;
}
}
return $ret;
}
/**
* 执行SQL语句,并返回影响的行数
*
* @param string $sql
* @return int
*/
public function execute($sql){
if(!is_string($sql)) return false;
return $this->pdo->exec(trim($sql));
}
/**
* 查询并返回结果集
*
* @param string $sql
* @return array[2]
*/
public function query($sql){
if(!is_string($sql)) return false;
return $this->pdo->query(trim($sql));
}
}
/**
* 本程序包的异常类
*
*/
class DalException extends Exception {
//所有异常情况
const DE_PARAMETER_TYPE = 1001;
const DE_UNKNOWN=2000;
//所有异常情况的文字表达
static private $msgs=array(
self::DE_PARAMETER_TYPE => '参数类型错误:类:<%s>的方法:<%s>的第<%d>个参数的类型应该是<%s>类型,但现在是<%s>类型,值为:<%s>',
self::DE_UNKNOWN => '未知错误'
);
public function __construct($code = 0,$msg=null) {
if(isset(self::$msgs[$code])){
if(is_string($msg)){
$message=$msg;
}else if(is_array($msg)){
$message=vsprintf(self::$msgs[$code],$msg);
}else{
$message=self::$msgs[$code];
}
}else{
$code=self::DE_UNKNOWN ;
if(is_string($msg)){
$message=$msg;
}else{
$message='错误代码:'.$code;
}
}
parent::__construct($message, $code);
}
}