Chinaunix首页 | 论坛 | 博客
  • 博客访问: 295457
  • 博文数量: 153
  • 博客积分: 3347
  • 博客等级: 中校
  • 技术积分: 1556
  • 用 户 组: 普通用户
  • 注册时间: 2009-12-30 17:50
文章分类

全部博文(153)

文章存档

2013年(7)

2012年(21)

2011年(46)

2010年(16)

2009年(63)

我的朋友

分类:

2009-12-30 18:53:59

/**
* 数据访问层,仅处理MYSQL
* 包括
* by:李勇
* at:2009-01-19
*/

/**
* 指定库中的指定表的访问类
*
     * 示例:
     *      $result=$table->select(array('id','name','birthday'),array('sex'=>1),null,null,'birthday',array(20,500))
     *      $table->delete(array('sex'=>0))
     *      $table->update(array('name'=>'tom jerry','weight'=>120),array('id'=>23149))
     *      $table->insert(array('id'=>uniqid(),'name'=>'mouse cat','height'=>'24cm'))
*/

include_once(rootpath."inc/exception.class.php");   //异常类

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)){
            throw new 
DalException(DalException::DE_TABLE_CONSTRUCTOR_TABLE_WRONG ,$tableName);
        }
        if(!
$tableName) {
            throw new 
DalException(DalException::DE_TABLE_CONSTRUCTOR_TABLE);
        }
        if(!
$pdo){
            throw new 
DalException(DalException::DE_TABLE_CONSTRUCTOR_PDO);
        }
        
$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;
            throw new 
DalException(DalException::DE_TABLE_META_NULL,$this->tableName);
        }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;
    }

    
/**
     * 执行查询语句,并根据结果数量分别处理
     *
     * @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 == 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){
            throw new 
DalException(DalException::DE_TABLE_INSERT_NULL,array($this->tableName,$row));
        }
        if(
is_object($row))$row get_object_vars($row);
        if(!
is_array($row)){
            throw new 
DalException(DalException::DE_TABLE_INSERT_WRONG,array($this->tableName,$row));
        }

        
$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) {
            throw new 
DalException(DalException::DE_TABLE_INSERT_FAILURE,array($this->tableName,$row,$sql));
        }
        return 
$this->pdo->lastInsertId();
    }

    
/**
     * 删除表中的部分数据
     *
     * @param mixed $where
     *      请参考createWhere
     * @return int
     */
    
public function delete($where){
        
$condition trim($this->createWhere($where));
        if(!
$condition){
            throw new 
DalException(DalException::DE_TABLE_DELETE_NO_WHERE,array($this->tableName,$where));
        }
        
$sql "DELETE FROM ".$this->tableName." ".$condition;
        return 
$this->execute($sql);
    }

    
/**
     * 统计满足条件的记录数
     *
     * @param mixed $where
     *      请参考createWhere
     * @return int
     */
    
public function count($where=null){
        
$condition trim($this->createWhere($where));
        
$sql "SELECT COUNT(*) AS cnt FROM ".$this->tableName;
        if(
$condition$sql .= " ".$condition;
        return 
intval($this->_select($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){
            throw new 
DalException(DalException::DE_TABLE_UPDATE_NULL,array($this->tableName,$row));
        }
        if(
is_object($row))$row get_object_vars($row);
        if(!
is_array($row)){
            throw new 
DalException(DalException::DE_TABLE_UPDATE_WRONG,array($this->tableName,$row));
        }

        
$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){
            throw new 
DalException(DalException::DE_TABLE_UPDATE_INVALID,array($this->tableName,$row));
        }

        
$condition $this->createWhere($where);
        if(!
$condition){
            throw new 
DalException(DalException::DE_TABLE_UPDATE_NO_WHERE,array($this->tableName,$where));
        }

        
$sql "UPDATE ".$this->tableName." SET ".$set." ".$condition;
        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)) {
            throw new 
DalException(DalException::DE_TABLE_FIELD_WRONG,array($this->tableName,$fields));
        }

        
$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)){
            throw new 
DalException(DalException::DE_TABLE_SORT_WRONG ,array($this->tableName,$sort));
        }

        if(
count($sort) == 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)){
            throw new 
DalException(DalException::DE_TABLE_LIMIT_WRONG ,array($this->tableName,$limit));
        }

        
$l null;
        
$o null;
        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(
$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];
        throw new 
DalException(DalException::DE_TABLE_LIMIT_COUNT ,array($this->tableName,$limit));
    }

    
/**
     * 生成条件表达式,用于Where,Having子句中
     *
     * @param mixed $condition
     *      string  直接使用
     *      numeric     主键值
     *      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_numeric($condition)){
            if(
$this->getPrimaryKey())
                return 
$this->getPrimaryKey()."='".$condition."' ";
            throw new 
DalException(DalException::DE_TABLE_CONDITION_PRIMARYKEY ,array($this->tableName,$condition));
        }

        if(
is_object($condition))$condition get_object_vars($condition);
        if(!
is_array($condition)){
            throw new 
DalException(DalException::DE_TABLE_CONDITION_WRONG ,array($this->tableName,$condition));
        }

        if(isset(
$condition['PrimaryKey'])){
            if(
$this->getPrimaryKey())
                return 
$this->getPrimaryKey()."='".mysql_escape_string($condition['PrimaryKey'])."'";
            throw new 
DalException(DalException::DE_TABLE_CONDITION_NO_PRIMARYKEY ,array($this->tableName,$condition));
        }

        
$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)) {
            throw new 
DalException(DalException::DE_TABLE_EXECUTE_STRING ,array($this->tableName,$sql));
        }
        return 
$this->pdo->exec(trim($sql));
    }

    
/**
     * 查询并返回结果集
     *
     * @param string $sql
     * @return array[2]
     */
    
public function query($sql){
        if(!
is_string($sql)) {
            throw new 
DalException(DalException::DE_TABLE_QUERY_STRING ,array($this->tableName,$sql));
        }
        
$statement=$this->pdo->query(trim($sql));
        return 
$statement->fetchAll();
    }
}

阅读(425) | 评论(0) | 转发(0) |
给主人留下些什么吧!~~