1. <?php
    /*
    * Copyright (c) 2018, 北京博习园教育科技有限公司
    * All rights reserved.
    *
    * 文件名称: xmodel.php
    * 摘 要: 模型公共类
    * 作 者: 刘泉皓
    * $Id$
    */
  2.  
  3. /**
    * 数据库连接类,依赖 PDO_MYSQL 扩展
    * walkor:在 https://github.com/auraphp/Aura.SqlQuery 的基础上修改而成
    * liuquanhao:在 https://github.com/walkor/mysql 的基础上修改而成
    */
  4.  
  5. require_once __DIR__ . '/' . '../../../config/config.php';
    require_once __DIR__ . '/' . '../function/cache.php';
    require_once __DIR__ . '/' . '../function/comm_func.php';
  6.  
  7. class XModel
    {
    /**
    * SELECT
    *
    * @var array
    */
    protected $union = array();
  8.  
  9. /**
    * 是否是更新
    *
    * @var bool
    */
    protected $for_update = false;
  10.  
  11. /**
    * 选择的列
    *
    * @var array
    */
    protected $cols = array();
  12.  
  13. /**
    * 从哪些表里面 SELECT
    *
    * @var array
    */
    protected $from = array();
  14.  
  15. /**
    * $from 当前的 key
    *
    * @var int
    */
    protected $from_key = -1;
  16.  
  17. /**
    * GROUP BY 的列
    *
    * @var array
    */
    protected $group_by = array();
  18.  
  19. /**
    * HAVING 条件数组.
    *
    * @var array
    */
    protected $having = array();
  20.  
  21. /**
    * HAVING 语句中绑定的值.
    *
    * @var array
    */
    protected $bind_having = array();
  22.  
  23. /**
    * 每页多少条记录
    *
    * @var int
    */
    protected $paging = 10;
  24.  
  25. /**
    * sql 中绑定的值
    *
    * @var array
    */
    protected $bind_values = array();
  26.  
  27. /**
    * WHERE 条件.
    *
    * @var array
    */
    protected $where = array();
  28.  
  29. /**
    * WHERE 语句绑定的值
    *
    * @var array
    */
    protected $bind_where = array();
  30.  
  31. /**
    * ORDER BY 的列
    *
    * @var array
    */
    protected $order_by = array();
  32.  
  33. /**
    * ORDER BY 的排序方式,默认为升序
    *
    * @var bool
    */
    protected $order_asc = true;
    /**
    * SELECT 多少记录
    *
    * @var int
    */
    protected $limit = 0;
  34.  
  35. /**
    * 返回记录的游标
    *
    * @var int
    */
    protected $offset = 0;
  36.  
  37. /**
    * flags 列表
    *
    * @var array
    */
    protected $flags = array();
  38.  
  39. /**
    * 操作哪个表
    *
    * @var string
    */
    protected $table;
  40.  
  41. /**
    * 表.列 和 last-insert-id 映射
    *
    * @var array
    */
    protected $last_insert_id_names = array();
  42.  
  43. /**
    * INSERT 或者 UPDATE 的列
    *
    * @param array
    */
    protected $col_values;
  44.  
  45. /**
    * 返回的列
    *
    * @var array
    */
    protected $returning = array();
  46.  
  47. /**
    * sql 的类型 SELECT INSERT DELETE UPDATE
    *
    * @var string
    */
    protected $type = '';
  48.  
  49. /**
    * pdo 实例
    *
    * @var PDO
    */
    protected $pdo;
  50.  
  51. /**
    * PDOStatement 实例
    *
    * @var PDOStatement
    */
    protected $sQuery;
  52.  
  53. /**
    * 数据库用户名密码等配置
    *
    * @var array
    */
    protected $readSettings = array();
    protected $writeSettings = array();
  54.  
  55. /**
    * sql 的参数
    *
    * @var array
    */
    protected $parameters = array();
  56.  
  57. /**
    * 最后一条直行的 sql
    *
    * @var string
    */
    protected $lastSql = '';
  58.  
  59. /**
    * 使用memcache
    *
    * @var object
    */
    protected $mem = null;
    /**
    * memcache key
    *
    * @var string
    */
    protected $memKey = '';
    /**
    * memcache active time
    *
    * @var int
    */
    protected $memTime = 0;
    /**
    * log
    *
    * @var boolean
    */
    protected $log = false;
    protected $logName = __CLASS__;
  60.  
  61. /**
    * 是否执行成功
    *
    * @var bool
    */
    protected $success = false;
  62.  
  63. /**
    * 构造函数
    */
    public function __construct($dbname = '')
    {
    if (!empty($dbname)) {
    $this->database($dbname);
    }
  64.  
  65. // 使用惰性连接
    //$this->connect();
    }
  66.  
  67. /*
    * 选择数据库
    */
    public function database($dbname)
    {
    switch ($dbname) {
    case 'tongzhuo_ask_db':
    $this->selectAskHost();
    break;
    case 'tongzhuonet_db':
    $this->selectTznetHost();
    break;
    case 'tongzhuo_weixin_db':
    $this->selectWeixinHost();
    break;
    case 'tongzhuo_user_db':
    $this->selectUserHost();
    break;
    case 'tongzhuo_examination_db':
    $this->selectExaminationHost();
    break;
    case 'tongzhuo_tv_db':
    $this->selectTvHost();
    break;
    case 'tongzhuo_db':
    $this->selectTzHost();
    break;
    default:
    throw new Exception('Not found database!');
    }
    return $this;
    }
  68.  
  69. /*
    * 使用memcache
    */
    public function mem($key = '', $activeTime = 0)
    {
    global $mem;
    $this->mem = $mem;
    $this->memKey = $key;
    $this->memTime = $activeTime;
    return $this;
    }
  70.  
  71. /**
    * 选择哪些列
    *
    * @param string|array $cols
    * @return self
    */
    public function select($cols = '*')
    {
    $this->type = 'SELECT';
    if (!is_array($cols)) {
    $cols = explode(',', $cols);
    }
    $this->cols($cols);
    return $this;
    }
  72.  
  73. /**
    * 从哪个表删除
    *
    * @param string $table
    * @return self
    */
    public function delete($table)
    {
    $this->type = 'DELETE';
    $this->table = $this->quoteName($table);
    $this->fromRaw($this->quoteName($table));
    return $this;
    }
  74.  
  75. /**
    * 从哪个表hash删除
    *
    * @param string $pre
    * @param string $salt
    * @return self
    */
    public function deleteHash($pre, $salt)
    {
    $table = $this->hashTable($pre, $salt);
    return $this->delete($table);
    }
  76.  
  77. /**
    * 更新哪个表
    *
    * @param string $table
    * @return self
    */
    public function update($table)
    {
    $this->type = 'UPDATE';
    $this->table = $this->quoteName($table);
    return $this;
    }
  78.  
  79. /**
    * 更新哪个hash表
    *
    * @param string $pre
    * @param string $salt
    * @return self
    */
    public function updateHash($pre, $salt)
    {
    $table = $this->hashTable($pre, $salt);
    return $this->update($table);
    }
  80.  
  81. /**
    * 向哪个表插入
    *
    * @param string $table
    * @return self
    */
    public function insert($table)
    {
    $this->type = 'INSERT';
    $this->table = $this->quoteName($table);
    return $this;
    }
  82.  
  83. /**
    * 向哪个hash表插入
    *
    * @param string $pre
    * @param string $hash
    * @return self
    */
    public function insertHash($pre, $salt)
    {
    $table = $this->hashTable($pre, $salt);
    return $this->insert($table);
    }
  84.  
  85. /**
    * from 哪个表
    *
    * @param string $table
    * @return self
    */
    public function from($table)
    {
    return $this->fromRaw($this->quoteName($table));
    }
  86.  
  87. /**
    * from 哪个hash表
    *
    * @param string $pre
    * @param string $salt
    * @return self
    */
    public function fromHash($pre, $salt)
    {
    $table = $this->hashTable($pre, $salt);
    return $this->from($table);
    }
  88.  
  89. /**
    * from的表
    *
    * @param string $table
    * @return self
    */
    public function fromRaw($table)
    {
    $this->from[] = array($table);
    $this->from_key++;
    return $this;
    }
  90.  
  91. /**
    *
    * 子查询
    *
    * @param string $table
    * @param string $name The alias name for the sub-select.
    * @return self
    */
    public function fromSubSelect($table, $name)
    {
    $this->from[] = array("($table) AS " . $this->quoteName($name));
    $this->from_key++;
    return $this;
    }
  92.  
  93. /**
    * 增加 join 语句
    *
    * @param string $table
    * @param string $cond
    * @param string $type
    * @return self
    * @throws Exception
    */
    public function join($table, $cond = null, $type = '')
    {
    return $this->joinInternal($type, $table, $cond);
    }
  94.  
  95. /**
    * 增加 join 语句
    *
    * @param string $join inner, left, natural
    * @param string $table
    * @param string $cond
    * @return self
    * @throws Exception
    */
    protected function joinInternal($join, $table, $cond = null)
    {
    if (!$this->from) {
    throw new Exception('Cannot join() without from()');
    }
  96.  
  97. $join = strtoupper(ltrim("$join JOIN"));
    $table = $this->quoteName($table);
    $cond = $this->fixJoinCondition($cond);
    $this->from[$this->from_key][] = rtrim("$join $table $cond");
    return $this;
    }
  98.  
  99. /**
    * left join
    *
    * @param string $table
    * @param string $cond
    * @return self
    * @throws Exception
    */
    public function leftJoin($table, $cond = null)
    {
    return $this->joinInternal('LEFT', $table, $cond);
    }
  100.  
  101. /**
    * right join
    *
    * @param string $table
    * @param string $cond
    * @return self
    * @throws Exception
    */
    public function rightJoin($table, $cond = null)
    {
    return $this->joinInternal('RIGHT', $table, $cond);
    }
  102.  
  103. /**
    * joinSubSelect
    *
    * @param string $join inner, left, natural
    * @param string $spec
    * @param string $name sub-select 的别名
    * @param string $cond
    * @return self
    * @throws Exception
    */
    public function joinSubSelect($join, $spec, $name, $cond = null)
    {
    if (!$this->from) {
    throw new Exception('Cannot join() without from() first.');
    }
  104.  
  105. $join = strtoupper(ltrim("$join JOIN"));
    $name = $this->quoteName($name);
    $cond = $this->fixJoinCondition($cond);
    $this->from[$this->from_key][] = rtrim("$join ($spec) AS $name $cond");
    return $this;
    }
  106.  
  107. /**
    * group by 语句
    *
    * @param array $cols
    * @return self
    */
    public function groupBy(array $cols)
    {
    foreach ($cols as $col) {
    $this->group_by[] = $this->quoteNamesIn($col);
    }
    return $this;
    }
  108.  
  109. /**
    * having 语句
    *
    * @param string $cond
    * @return self
    */
    public function having($cond)
    {
    $this->addClauseCondWithBind('having', 'AND', func_get_args());
    return $this;
    }
  110.  
  111. /**
    * or having 语句
    *
    * @param string $cond The HAVING condition.
    * @return self
    */
    public function orHaving($cond)
    {
    $this->addClauseCondWithBind('having', 'OR', func_get_args());
    return $this;
    }
  112.  
  113. /*
    * 重连tv读写数据库
    */
    protected function selectTvHost()
    {
    $this->readSettings['user'] = $GLOBALS['user_tv_read'];
    $this->readSettings['password'] = $GLOBALS['pw_tv_read'];
    $this->readSettings['host'] = $GLOBALS['host_tv_read'];
    $this->readSettings['port'] = $GLOBALS['port_tv_read'];
    $this->readSettings['dbname'] = $GLOBALS['database_tv_read'];
    $this->writeSettings['user'] = $GLOBALS['user_tv_write'];
    $this->writeSettings['password'] = $GLOBALS['pw_tv_write'];
    $this->writeSettings['host'] = $GLOBALS['host_tv_write'];
    $this->writeSettings['port'] = $GLOBALS['port_tv_write'];
    $this->writeSettings['dbname'] = $GLOBALS['database_tv_write'];
    }
  114.  
  115. /*
    * 重连ask读写数据库
    */
    protected function selectAskHost()
    {
    $this->readSettings['user'] = $GLOBALS['user_ask_read'];
    $this->readSettings['password'] = $GLOBALS['pw_ask_read'];
    $this->readSettings['host'] = $GLOBALS['host_ask_read'];
    $this->readSettings['port'] = $GLOBALS['port_ask_read'];
    $this->readSettings['dbname'] = $GLOBALS['database_ask_read'];
    $this->writeSettings['user'] = $GLOBALS['user_ask_write'];
    $this->writeSettings['password'] = $GLOBALS['pw_ask_write'];
    $this->writeSettings['host'] = $GLOBALS['host_ask_write'];
    $this->writeSettings['port'] = $GLOBALS['port_ask_write'];
    $this->writeSettings['dbname'] = $GLOBALS['database_ask_write'];
    }
    /*
    * 重连net读写数据库
    */
    protected function selectTznetHost()
    {
    $this->readSettings['user'] = $GLOBALS['user_tz_read'];
    $this->readSettings['password'] = $GLOBALS['pw_tz_read'];
    $this->readSettings['host'] = $GLOBALS['host_tz_read'];
    $this->readSettings['port'] = $GLOBALS['port_tz_read'];
    $this->readSettings['dbname'] = $GLOBALS['database_tz_read'];
    $this->writeSettings['user'] = $GLOBALS['user_tz_write'];
    $this->writeSettings['password'] = $GLOBALS['pw_tz_write'];
    $this->writeSettings['host'] = $GLOBALS['host_tz_write'];
    $this->writeSettings['port'] = $GLOBALS['port_tz_write'];
    $this->writeSettings['dbname'] = $GLOBALS['database_tz_write'];
    }
    /*
    * 重连weixin读写数据库
    */
    protected function selectWeixinHost()
    {
    $this->readSettings['user'] = $GLOBALS['user_wx_read'];
    $this->readSettings['password'] = $GLOBALS['pw_wx_read'];
    $this->readSettings['host'] = $GLOBALS['host_wx_read'];
    $this->readSettings['port'] = $GLOBALS['port_wx_read'];
    $this->readSettings['dbname'] = $GLOBALS['database_wx_read'];
    $this->writeSettings['user'] = $GLOBALS['user_wx_write'];
    $this->writeSettings['password'] = $GLOBALS['pw_wx_write'];
    $this->writeSettings['host'] = $GLOBALS['host_wx_write'];
    $this->writeSettings['port'] = $GLOBALS['port_wx_write'];
    $this->writeSettings['dbname'] = $GLOBALS['database_wx_write'];
    }
    /*
    * 重连用户日志读写数据库
    */
    protected function selectUserHost()
    {
    $this->readSettings['user'] = $GLOBALS['user_user_read'];
    $this->readSettings['password'] = $GLOBALS['pw_user_read'];
    $this->readSettings['host'] = $GLOBALS['host_user_read'];
    $this->readSettings['port'] = $GLOBALS['port_user_read'];
    $this->readSettings['dbname'] = $GLOBALS['database_user_read'];
    $this->writeSettings['user'] = $GLOBALS['user_user_write'];
    $this->writeSettings['password'] = $GLOBALS['pw_user_write'];
    $this->writeSettings['host'] = $GLOBALS['host_user_write'];
    $this->writeSettings['port'] = $GLOBALS['port_user_write'];
    $this->writeSettings['dbname'] = $GLOBALS['database_user_write'];
    }
    /*
    * 模拟考试读写数据库
    */
    protected function selectExaminationHost()
    {
    $this->readSettings['user'] = $GLOBALS['user_ex_read'];
    $this->readSettings['password'] = $GLOBALS['pw_ex_read'];
    $this->readSettings['host'] = $GLOBALS['host_ex_read'];
    $this->readSettings['port'] = $GLOBALS['port_ex_read'];
    $this->readSettings['dbname'] = $GLOBALS['database_ex_read'];
    $this->writeSettings['user'] = $GLOBALS['user_user_write'];
    $this->writeSettings['password'] = $GLOBALS['pw_ex_write'];
    $this->writeSettings['host'] = $GLOBALS['host_ex_write'];
    $this->writeSettings['port'] = $GLOBALS['port_ex_write'];
    $this->writeSettings['dbname'] = $GLOBALS['database_ex_write'];
    }
    /*
    * 重连tongzhuo读写数据库
    */
    protected function selectTzHost()
    {
    $this->readSettings['user'] = $GLOBALS['user_one_read'];
    $this->readSettings['password'] = $GLOBALS['pw_one_read'];
    $this->readSettings['host'] = $GLOBALS['host_one_read'];
    $this->readSettings['port'] = $GLOBALS['port_one_read'];
    $this->readSettings['dbname'] = $GLOBALS['database_one_read'];
    $this->writeSettings['user'] = $GLOBALS['user_one_write'];
    $this->writeSettings['password'] = $GLOBALS['pw_one_write'];
    $this->writeSettings['host'] = $GLOBALS['host_one_write'];
    $this->writeSettings['port'] = $GLOBALS['port_one_write'];
    $this->writeSettings['dbname'] = $GLOBALS['database_one_write'];
    }
  116.  
  117. /**
    * 创建 PDO 实例
    */
    protected function connect()
    {
    if ($this->type == 'SELECT') {
    if (
    empty($this->readSettings['dbname']) &&
    empty($this->readSettings['host']) &&
    empty($this->readSettings['port']) &&
    empty($this->readSettings['user']) &&
    empty($this->readSettings['password'])) {
    throw new Exception('Database configuration fail!');
    }
    $dsn = 'mysql:dbname=' . $this->readSettings['dbname'] .
    ';host=' . $this->readSettings['host'] . ';port=' . $this->readSettings['port'] .
    ';charset=utf8';
    $this->pdo = new PDO(
    $dsn,
    $this->readSettings['user'],
    $this->readSettings['password']
    );
    } else {
    if (
    empty($this->writeSettings['dbname']) &&
    empty($this->writeSettings['host']) &&
    empty($this->writeSettings['port']) &&
    empty($this->writeSettings['user']) &&
    empty($this->writeSettings['password'])) {
    throw new Exception('Database configuration fail!');
    }
    $dsn = 'mysql:dbname=' . $this->writeSettings['dbname'] .
    ';host=' . $this->writeSettings['host'] . ';port=' . $this->writeSettings['port'] .
    ';charset=utf8';
    $this->pdo = new PDO(
    $dsn,
    $this->writeSettings['user'],
    $this->writeSettings['password']
    );
    }
    $this->pdo->setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION);
    $this->pdo->setAttribute(PDO::ATTR_STRINGIFY_FETCHES, false);
    $this->pdo->setAttribute(PDO::ATTR_EMULATE_PREPARES, false);
    }
  118.  
  119. /*
    * 清空本次mem设置信息
    */
    protected function resetMem()
    {
    $this->mem = null;
    $this->memKey = '';
    $this->memTime = 0;
    }
  120.  
  121. /**
    * 关闭连接
    */
    public function closeConnection()
    {
    $this->pdo = null;
    }
    /**
    *
    * 设置 SQL_CALC_FOUND_ROWS 标记.
    *
    * @param bool $enable
    * @return self
    */
    public function calcFoundRows($enable = true)
    {
    $this->setFlag('SQL_CALC_FOUND_ROWS', $enable);
    return $this;
    }
  122.  
  123. /**
    * 设置 SQL_CACHE 标记
    *
    * @param bool $enable
    * @return self
    */
    public function cache($enable = true)
    {
    $this->setFlag('SQL_CACHE', $enable);
    return $this;
    }
  124.  
  125. /**
    * 设置 SQL_NO_CACHE 标记
    *
    * @param bool $enable
    * @return self
    */
    public function noCache($enable = true)
    {
    $this->setFlag('SQL_NO_CACHE', $enable);
    return $this;
    }
  126.  
  127. /**
    * 设置 STRAIGHT_JOIN 标记.
    *
    * @param bool $enable
    * @return self
    */
    public function straightJoin($enable = true)
    {
    $this->setFlag('STRAIGHT_JOIN', $enable);
    return $this;
    }
  128.  
  129. /**
    * 设置 HIGH_PRIORITY 标记
    *
    * @param bool $enable
    * @return self
    */
    public function highPriority($enable = true)
    {
    $this->setFlag('HIGH_PRIORITY', $enable);
    return $this;
    }
  130.  
  131. /**
    * 设置 SQL_SMALL_RESULT 标记
    *
    * @param bool $enable
    * @return self
    */
    public function smallResult($enable = true)
    {
    $this->setFlag('SQL_SMALL_RESULT', $enable);
    return $this;
    }
  132.  
  133. /**
    * 设置 SQL_BIG_RESULT 标记
    *
    * @param bool $enable
    * @return self
    */
    public function bigResult($enable = true)
    {
    $this->setFlag('SQL_BIG_RESULT', $enable);
    return $this;
    }
  134.  
  135. /**
    * 设置 SQL_BUFFER_RESULT 标记
    *
    * @param bool $enable
    * @return self
    */
    public function bufferResult($enable = true)
    {
    $this->setFlag('SQL_BUFFER_RESULT', $enable);
    return $this;
    }
  136.  
  137. /**
    * 设置 DISTINCT 标记
    *
    * @param bool $enable
    * @return self
    */
    public function distinct($enable = true)
    {
    $this->setFlag('DISTINCT', $enable);
    return $this;
    }
  138.  
  139. /**
    * 设置 LOW_PRIORITY 标记
    *
    * @param bool $enable
    * @return self
    */
    public function lowPriority($enable = true)
    {
    $this->setFlag('LOW_PRIORITY', $enable);
    return $this;
    }
  140.  
  141. /**
    * 设置 IGNORE 标记
    *
    * @param bool $enable
    * @return self
    */
    public function ignore($enable = true)
    {
    $this->setFlag('IGNORE', $enable);
    return $this;
    }
  142.  
  143. /**
    * 设置 QUICK 标记
    *
    * @param bool $enable
    * @return self
    */
    public function quick($enable = true)
    {
    $this->setFlag('QUICK', $enable);
    return $this;
    }
  144.  
  145. /**
    * 设置 DELAYED 标记
    *
    * @param bool $enable
    * @return self
    */
    public function delayed($enable = true)
    {
    $this->setFlag('DELAYED', $enable);
    return $this;
    }
  146.  
  147. /**
    * 设置 FOR UPDATE 标记
    *
    * @param bool $enable
    * @return self
    */
    public function forUpdate($enable = true)
    {
    $this->for_update = (bool) $enable;
    return $this;
    }
  148.  
  149. /**
    * 设置每页多少条记录
    *
    * @param int $paging
    * @return self
    */
    public function setPaging($paging)
    {
    $this->paging = (int) $paging;
    return $this;
    }
  150.  
  151. /**
    * 获取每页多少条记录
    *
    * @return int
    */
    public function getPaging()
    {
    return $this->paging;
    }
  152.  
  153. /**
    * 序列化
    *
    * @return string
    */
    public function __toString()
    {
    $union = '';
    if ($this->union) {
    $union = implode(' ', $this->union) . ' ';
    }
    return $union . $this->build();
    }
  154.  
  155. /**
    * 获取绑定在占位符上的值
    */
    public function getBindValues()
    {
    switch ($this->type) {
    case 'SELECT':
    return $this->getBindValuesSELECT();
    case 'DELETE':
    case 'UPDATE':
    case 'INSERT':
    return $this->getBindValuesCOMMON();
    default:
    throw new Exception("type err");
    }
    }
  156.  
  157. /**
    * 获取绑定在占位符上的值
    *
    * @return array
    */
    public function getBindValuesSELECT()
    {
    $bind_values = $this->bind_values;
    $i = 1;
    foreach ($this->bind_where as $val) {
    $bind_values[$i] = $val;
    $i++;
    }
    foreach ($this->bind_having as $val) {
    $bind_values[$i] = $val;
    $i++;
    }
    return $bind_values;
    }
  158.  
  159. /**
    *
    * SELECT选择哪些列
    *
    * @param mixed $key
    * @param string $val
    * @return void
    */
    protected function addColSELECT($col, $alias)
    {
    if (is_string($col)) {
    $this->cols[$alias] = $col;
    } else {
    $this->addColWithAlias($alias);
    }
    }
  160.  
  161. /**
    * SELECT 增加选择的列
    *
    * @param string $spec
    */
    protected function addColWithAlias($spec)
    {
    $parts = explode(' ', trim($spec));
    $count = count($parts);
    if ($count == 2) {
    $this->cols[$parts[1]] = $parts[0];
    } elseif ($count == 3 && strtoupper($parts[1]) == 'AS') {
    $this->cols[$parts[2]] = $parts[0];
    } else {
    $this->cols[] = $spec;
    }
    }
  162.  
  163. /**
    * quote
    *
    * @param string $cond
    * @return string
    *
    */
    protected function fixJoinCondition($cond)
    {
    if (!$cond) {
    return '';
    }
  164.  
  165. $cond = $this->quoteNamesIn($cond);
  166.  
  167. if (strtoupper(substr(ltrim($cond), 0, 3)) == 'ON ') {
    return $cond;
    }
  168.  
  169. if (strtoupper(substr(ltrim($cond), 0, 6)) == 'USING ') {
    return $cond;
    }
  170.  
  171. return 'ON ' . $cond;
    }
  172.  
  173. /**
    * inner join
    *
    * @param string $table
    * @param string $cond
    * @return self
    * @throws Exception
    */
    public function innerJoin($table, $cond = null)
    {
    return $this->joinInternal('INNER', $table, $cond);
    }
    /**
    * 设置每页的记录数量
    *
    * @param int $page
    * @return self
    */
    public function page($page)
    {
    $this->limit = 0;
    $this->offset = 0;
  174.  
  175. $page = (int) $page;
    if ($page > 0) {
    $this->limit = $this->paging;
    $this->offset = $this->paging * ($page - 1);
    }
    return $this;
    }
  176.  
  177. /**
    * union
    *
    * @return self
    */
    public function union()
    {
    $this->union[] = $this->build() . ' UNION';
    $this->reset();
    return $this;
    }
  178.  
  179. /**
    * unionAll
    *
    * @return self
    */
    public function unionAll()
    {
    $this->union[] = $this->build() . ' UNION ALL';
    $this->reset();
    return $this;
    }
  180.  
  181. /**
    * 重置
    */
    protected function reset()
    {
    $this->resetFlags();
    $this->cols = array();
    $this->from = array();
    $this->from_key = -1;
    $this->where = array();
    $this->group_by = array();
    $this->having = array();
    $this->order_by = array();
    $this->limit = 0;
    $this->offset = 0;
    $this->for_update = false;
    }
  182.  
  183. /**
    * 清除所有数据
    */
    protected function resetAll()
    {
    $this->union = array();
    $this->for_update = false;
    $this->cols = array();
    $this->from = array();
    $this->from_key = -1;
    $this->group_by = array();
    $this->having = array();
    $this->bind_having = array();
    $this->paging = 10;
    $this->bind_values = array();
    $this->where = array();
    $this->bind_where = array();
    $this->order_by = array();
    $this->limit = 0;
    $this->offset = 0;
    $this->flags = array();
    $this->table = '';
    $this->last_insert_id_names = array();
    $this->col_values = array();
    $this->returning = array();
    $this->parameters = array();
    }
  184.  
  185. /**
    * 创建 SELECT SQL
    *
    * @return string
    */
    protected function buildSELECT()
    {
    return 'SELECT'
    . $this->buildFlags()
    . $this->buildCols()
    . $this->buildFrom()
    . $this->buildWhere()
    . $this->buildGroupBy()
    . $this->buildHaving()
    . $this->buildOrderBy()
    . $this->buildLimit()
    . $this->buildForUpdate();
    }
  186.  
  187. /**
    * 创建 DELETE SQL
    */
    protected function buildDELETE()
    {
    return 'DELETE'
    . $this->buildFlags()
    . $this->buildFrom()
    . $this->buildWhere()
    . $this->buildOrderBy()
    . $this->buildLimit()
    . $this->buildReturning();
    }
  188.  
  189. /**
    * 生成 SELECT 列语句
    *
    * @return string
    * @throws Exception
    */
    protected function buildCols()
    {
    if (!$this->cols) {
    throw new Exception('No columns in the SELECT.');
    }
  190.  
  191. $cols = array();
    foreach ($this->cols as $key => $val) {
    if (is_int($key)) {
    $cols[] = $this->quoteNamesIn($val);
    } else {
    $cols[] = $this->quoteNamesIn("$val AS $key");
    }
    }
  192.  
  193. return $this->indentCsv($cols);
    }
  194.  
  195. /**
    * 生成 FROM 语句.
    *
    * @return string
    */
    protected function buildFrom()
    {
    if (!$this->from) {
    return '';
    }
  196.  
  197. $refs = array();
    foreach ($this->from as $from) {
    $refs[] = implode(' ', $from);
    }
    return ' FROM' . $this->indentCsv($refs);
    }
  198.  
  199. /**
    * 生成 GROUP BY 语句.
    *
    * @return string
    */
    protected function buildGroupBy()
    {
    if (!$this->group_by) {
    return '';
    }
    return ' GROUP BY' . $this->indentCsv($this->group_by);
    }
  200.  
  201. /**
    * 生成 HAVING 语句.
    *
    * @return string
    */
    protected function buildHaving()
    {
    if (!$this->having) {
    return '';
    }
    return ' HAVING' . $this->indent($this->having);
    }
  202.  
  203. /**
    * 生成 FOR UPDATE 语句
    *
    * @return string
    */
    protected function buildForUpdate()
    {
    if (!$this->for_update) {
    return '';
    }
    return ' FOR UPDATE';
    }
  204.  
  205. /**
    * where
    *
    * @param string|array $cond
    * @return self
    */
    public function where($cond)
    {
    if (is_array($cond)) {
    foreach ($cond as $key => $val) {
    if (is_string($key)) {
    $this->addWhere('AND', array($key, $val));
    } else {
    $this->addWhere('AND', array($val));
    }
    }
    } else {
    $this->addWhere('AND', func_get_args());
    }
    return $this;
    }
  206.  
  207. /**
    * or where
    *
    * @param string|array $cond
    * @return self
    */
    public function orWhere($cond)
    {
    if (is_array($cond)) {
    foreach ($cond as $key => $val) {
    if (is_string($key)) {
    $this->addWhere('OR', array($key, $val));
    } else {
    $this->addWhere('OR', array($val));
    }
    }
    } else {
    $this->addWhere('OR', func_get_args());
    }
    return $this;
    }
  208.  
  209. /**
    * limit
    *
    * @param int $limit
    * @return self
    */
    public function limit($limit)
    {
    $this->limit = (int) $limit;
    return $this;
    }
  210.  
  211. /**
    * limit offset
    *
    * @param int $offset
    * @return self
    */
    public function offset($offset)
    {
    $this->offset = (int) $offset;
    return $this;
    }
  212.  
  213. /**
    * orderby.
    *
    * @param array $cols
    * @return self
    */
    public function orderBy(array $cols)
    {
    return $this->addOrderBy($cols);
    }
  214.  
  215. /**
    * order by ASC OR DESC
    *
    * @param array $cols
    * @param bool $order_asc
    * @return self
    */
    public function orderByASC(array $cols, $order_asc = true)
    {
    $this->order_asc = $order_asc;
    return $this->addOrderBy($cols);
    }
  216.  
  217. /**
    * order by DESC
    *
    * @param array $cols
    * @return self
    */
    public function orderByDESC(array $cols)
    {
    $this->order_asc = false;
    return $this->addOrderBy($cols);
    }
  218.  
  219. // -------------abstractquery----------
    /**
    * 返回逗号分隔的字符串
    *
    * @param array $list
    * @return string
    */
    protected function indentCsv(array $list)
    {
    return ' ' . implode(',', $list);
    }
  220.  
  221. /**
    * 返回空格分隔的字符串
    *
    * @param array $list
    * @return string
    */
    protected function indent(array $list)
    {
    return ' ' . implode(' ', $list);
    }
  222.  
  223. /**
    * 批量为占位符绑定值
    *
    * @param array $bind_values
    * @return self
    *
    */
    public function bindValues(array $bind_values)
    {
    foreach ($bind_values as $key => $val) {
    $this->bindValue($key, $val);
    }
    return $this;
    }
  224.  
  225. /**
    * 单个为占位符绑定值
    *
    * @param string $name
    * @param mixed $value
    * @return self
    */
    public function bindValue($name, $value)
    {
    $this->bind_values[$name] = $value;
    return $this;
    }
  226.  
  227. /**
    * 生成 flag
    *
    * @return string
    */
    protected function buildFlags()
    {
    if (!$this->flags) {
    return '';
    }
    return ' ' . implode(' ', array_keys($this->flags));
    }
  228.  
  229. /**
    * 设置 flag.
    *
    * @param string $flag
    * @param bool $enable
    */
    protected function setFlag($flag, $enable = true)
    {
    if ($enable) {
    $this->flags[$flag] = true;
    } else {
    unset($this->flags[$flag]);
    }
    }
  230.  
  231. /**
    * 重置 flag
    */
    protected function resetFlags()
    {
    $this->flags = array();
    }
  232.  
  233. /**
    *
    * 添加 where 语句
    *
    * @param string $andor 'AND' or 'OR
    * @param array $conditions
    * @return self
    *
    */
    protected function addWhere($andor, $conditions)
    {
    $this->addClauseCondWithBind('where', $andor, $conditions);
    return $this;
    }
  234.  
  235. /**
    * 添加条件和绑定值
    *
    * @param string $clause where 、having等
    * @param string $andor AND、OR等
    * @param array $conditions
    */
    protected function addClauseCondWithBind($clause, $andor, $conditions)
    {
    $cond = array_shift($conditions);
    $cond = $this->quoteNamesIn($cond);
  236.  
  237. $bind = &$this->{"bind_{$clause}"};
    foreach ($conditions as $value) {
    $bind[] = $value;
    }
  238.  
  239. $clause = &$this->$clause;
    if ($clause) {
    $clause[] = "$andor $cond";
    } else {
    $clause[] = $cond;
    }
    }
  240.  
  241. /**
    * 生成 where 语句
    *
    * @return string
    */
    protected function buildWhere()
    {
    if (!$this->where) {
    return '';
    }
    return ' WHERE' . $this->indent($this->where);
    }
  242.  
  243. /**
    * 增加 order by
    *
    * @param array $spec The columns and direction to order by.
    * @return self
    */
    protected function addOrderBy(array $spec)
    {
    foreach ($spec as $col) {
    $this->order_by[] = $this->quoteNamesIn($col);
    }
    return $this;
    }
  244.  
  245. /**
    * 生成 order by 语句
    *
    * @return string
    */
    protected function buildOrderBy()
    {
    if (!$this->order_by) {
    return '';
    }
  246.  
  247. if ($this->order_asc) {
    return ' ORDER BY' . $this->indentCsv($this->order_by) . ' ASC';
    } else {
    return ' ORDER BY' . $this->indentCsv($this->order_by) . ' DESC';
    }
    }
  248.  
  249. /**
    * 生成 limit 语句
    *
    * @return string
    */
    protected function buildLimit()
    {
    $has_limit = $this->type == 'DELETE' || $this->type == 'UPDATE';
    $has_offset = $this->type == 'SELECT';
  250.  
  251. if ($has_offset && $this->limit) {
    $clause = " LIMIT {$this->limit}";
    if ($this->offset) {
    $clause .= " OFFSET {$this->offset}";
    }
    return $clause;
    } elseif ($has_limit && $this->limit) {
    return " LIMIT {$this->limit}";
    }
    return '';
    }
  252.  
  253. /**
    * Quotes
    *
    * @param string $spec
    * @return string|array
    */
    public function quoteName($spec)
    {
    $spec = trim($spec);
    $seps = array(' AS ', ' ', '.');
    foreach ($seps as $sep) {
    $pos = strripos($spec, $sep);
    if (false !== $pos) {
    return $this->quoteNameWithSeparator($spec, $sep, $pos);
    }
    }
    return $this->replaceName($spec);
    }
  254.  
  255. /**
    * 指定分隔符的 Quotes
    *
    * @param string $spec
    * @param string $sep
    * @param int $pos
    * @return string
    */
    protected function quoteNameWithSeparator($spec, $sep, $pos)
    {
    $len = strlen($sep);
    $part1 = $this->quoteName(substr($spec, 0, $pos));
    $part2 = $this->replaceName(substr($spec, $pos + $len));
    return "{$part1}{$sep}{$part2}";
    }
  256.  
  257. /**
    * Quotes "table.col" 格式的字符串
    *
    * @param string $text
    * @return string|array
    */
    public function quoteNamesIn($text)
    {
    $list = $this->getListForQuoteNamesIn($text);
    $last = count($list) - 1;
    $text = null;
    foreach ($list as $key => $val) {
    if (($key + 1) % 3) {
    $text .= $this->quoteNamesInLoop($val, $key == $last);
    }
    }
    return $text;
    }
  258.  
  259. /**
    * 返回 quote 元素列表
    *
    * @param string $text
    * @return array
    */
    protected function getListForQuoteNamesIn($text)
    {
    $apos = "'";
    $quot = '"';
    return preg_split(
    "/(($apos+|$quot+|\\$apos+|\\$quot+).*?\\2)/",
    $text,
    -1,
    PREG_SPLIT_DELIM_CAPTURE
    );
    }
  260.  
  261. /**
    * 循环 quote
    *
    * @param string $val
    * @param bool $is_last
    * @return string
    */
    protected function quoteNamesInLoop($val, $is_last)
    {
    if ($is_last) {
    return $this->replaceNamesAndAliasIn($val);
    }
    return $this->replaceNamesIn($val);
    }
  262.  
  263. /**
    * 替换成别名
    *
    * @param string $val
    * @return string
    */
    protected function replaceNamesAndAliasIn($val)
    {
    $quoted = $this->replaceNamesIn($val);
    $pos = strripos($quoted, ' AS ');
    if ($pos !== false) {
    $alias = $this->replaceName(substr($quoted, $pos + 4));
    $quoted = substr($quoted, 0, $pos) . " AS $alias";
    }
    return $quoted;
    }
  264.  
  265. /**
    * Quotes name
    *
    * @param string $name
    * @return string
    */
    protected function replaceName($name)
    {
    $name = trim($name);
    if ($name == '*') {
    return $name;
    }
    return '`' . $name . '`';
    }
  266.  
  267. /**
    * Quotes
    *
    * @param string $text
    * @return string|array
    */
    protected function replaceNamesIn($text)
    {
    $is_string_literal = strpos($text, "'") !== false
    || strpos($text, '"') !== false;
    if ($is_string_literal) {
    return $text;
    }
  268.  
  269. $word = '[a-z_][a-z0-9_]*';
  270.  
  271. $find = "/(\\b)($word)\\.($word)(\\b)/i";
  272.  
  273. $repl = '$1`$2`.`$3`$4';
  274.  
  275. $text = preg_replace($find, $repl, $text);
  276.  
  277. return $text;
    }
  278.  
  279. // ---------- insert --------------
    /**
    * 设置 `table.column` 与 last-insert-id 的映射
    *
    * @param array $last_insert_id_names
    */
    public function setLastInsertIdNames(array $last_insert_id_names)
    {
    $this->last_insert_id_names = $last_insert_id_names;
    }
  280.  
  281. /**
    * insert into.
    *
    * @param string $table
    * @return self
    */
    public function into($table)
    {
    $this->table = $this->quoteName($table);
    return $this;
    }
  282.  
  283. /**
    * 生成 INSERT 语句
    *
    * @return string
    */
    protected function buildINSERT()
    {
    return 'INSERT'
    . $this->buildFlags()
    . $this->buildInto()
    . $this->buildValuesForInsert()
    . $this->buildReturning();
    }
  284.  
  285. /**
    * 生成 INTO 语句
    *
    * @return string
    */
    protected function buildInto()
    {
    return " INTO " . $this->table;
    }
  286.  
  287. /**
    * PDO::lastInsertId()
    *
    * @param string $col
    * @return mixed
    */
    public function getLastInsertIdName($col)
    {
    $key = str_replace('`', '', $this->table) . '.' . $col;
    if (isset($this->last_insert_id_names[$key])) {
    return $this->last_insert_id_names[$key];
    }
  288.  
  289. return null;
    }
  290.  
  291. /**
    * 设置一列,如果有第二各参数,则把第二个参数绑定在占位符上
    *
    * @param string $col
    * @return self
    */
    public function col($col)
    {
    return call_user_func_array(array($this, 'addCol'), func_get_args());
    }
  292.  
  293. /**
    * 设置多列
    *
    * @param array $cols
    * @return self
    */
    public function cols(array $cols)
    {
    if ($this->type == 'SELECT') {
    foreach ($cols as $key => $val) {
    $this->addColSELECT($key, $val);
    }
    return $this;
    }
    return $this->addCols($cols);
    }
  294.  
  295. /**
    * 直接设置列的值
    *
    * @param string $col
    * @param string $value
    * @return self
    */
    public function set($col, $value)
    {
    return $this->setCol($col, $value);
    }
  296.  
  297. /**
    * 为 INSERT 语句绑定值
    *
    * @return string
    */
    protected function buildValuesForInsert()
    {
    return ' (' . $this->indentCsv(array_keys($this->col_values)) . ') VALUES (' .
    $this->indentCsv(array_values($this->col_values)) . ')';
    }
  298.  
  299. // ------update-------
    /**
    * 更新哪个表
    *
    * @param string $table
    * @return self
    */
    public function table($table)
    {
    $this->table = $this->quoteName($table);
    return $this;
    }
  300.  
  301. /**
    * 生成完整 SQL 语句
    *
    * @return string
    * @throws Exception
    */
    protected function build()
    {
    switch ($this->type) {
    case 'DELETE':
    return $this->buildDELETE();
    case 'INSERT':
    return $this->buildINSERT();
    case 'UPDATE':
    return $this->buildUPDATE();
    case 'SELECT':
    return $this->buildSELECT();
    }
    throw new Exception("type empty");
    }
  302.  
  303. /**
    * 生成更新的 SQL 语句
    */
    protected function buildUPDATE()
    {
    return 'UPDATE'
    . $this->buildFlags()
    . $this->buildTable()
    . $this->buildValuesForUpdate()
    . $this->buildWhere()
    . $this->buildOrderBy()
    . $this->buildLimit()
    . $this->buildReturning();
    }
  304.  
  305. /**
    * 哪个表
    *
    * @return string
    */
    protected function buildTable()
    {
    return " {$this->table}";
    }
  306.  
  307. /**
    * 为更新语句绑定值
    *
    * @return string
    */
    protected function buildValuesForUpdate()
    {
    $values = array();
    foreach ($this->col_values as $col => $value) {
    $values[] = "{$col} = {$value}";
    }
    return ' SET' . $this->indentCsv($values);
    }
  308.  
  309. // ----------Dml---------------
    /**
    * 获取绑定的值
    *
    * @return array
    */
    public function getBindValuesCOMMON()
    {
    $bind_values = $this->bind_values;
    $i = 1;
    foreach ($this->bind_where as $val) {
    $bind_values[$i] = $val;
    $i++;
    }
    return $bind_values;
    }
  310.  
  311. /**
    * 设置列
    *
    * @param string $col
    * @return self
    */
    protected function addCol($col)
    {
    $key = $this->quoteName($col);
    $this->col_values[$key] = ":$col";
    $args = func_get_args();
    if (count($args) > 1) {
    $this->bindValue($col, $args[1]);
    }
    return $this;
    }
  312.  
  313. /**
    * 设置多个列
    *
    * @param array $cols
    * @return self
    */
    protected function addCols(array $cols)
    {
    foreach ($cols as $key => $val) {
    if (is_int($key)) {
    $this->addCol($val);
    } else {
    $this->addCol($key, $val);
    }
    }
    return $this;
    }
  314.  
  315. /**
    * 设置单列的值
    *
    * @param string $col .
    * @param string $value
    * @return self
    */
    protected function setCol($col, $value)
    {
    if ($value === null) {
    $value = 'NULL';
    }
  316.  
  317. $key = $this->quoteName($col);
    $value = $this->quoteNamesIn($value);
    $this->col_values[$key] = $value;
    return $this;
    }
  318.  
  319. /**
    * 增加返回的列
    *
    * @param array $cols
    * @return self
    *
    */
    protected function addReturning(array $cols)
    {
    foreach ($cols as $col) {
    $this->returning[] = $this->quoteNamesIn($col);
    }
    return $this;
    }
  320.  
  321. /**
    * 生成 RETURNING 语句
    *
    * @return string
    */
    protected function buildReturning()
    {
    if (!$this->returning) {
    return '';
    }
    return ' RETURNING' . $this->indentCsv($this->returning);
    }
  322.  
  323. /**
    * 执行
    *
    * @param string $query
    * @param string $parameters
    * @throws PDOException
    */
    protected function execute($query, $parameters = "")
    {
    try {
    $this->connect();
    $this->sQuery = @$this->pdo->prepare($query);
    $this->bindMore($parameters);
    if (!empty($this->parameters)) {
    foreach ($this->parameters as $param) {
    $parameters = explode("\x7F", $param);
    $this->sQuery->bindParam($parameters[0], $parameters[1]);
    }
    }
    $this->success = $this->sQuery->execute();
    } catch (PDOException $e) {
    // 服务端断开时重连一次
    if ($e->errorInfo[1] == 2006 || $e->errorInfo[1] == 2013) {
    $this->closeConnection();
    try {
    $this->connect();
    $this->sQuery = $this->pdo->prepare($query);
    $this->bindMore($parameters);
    if (!empty($this->parameters)) {
    foreach ($this->parameters as $param) {
    $parameters = explode("\x7F", $param);
    $this->sQuery->bindParam($parameters[0], $parameters[1]);
    }
    }
    $this->success = $this->sQuery->execute();
    } catch (PDOException $ex) {
    $this->rollBackTrans();
    throw $ex;
    }
    } else {
    $this->rollBackTrans();
    $msg = $e->getMessage();
    $err_msg = "SQL:" . $this->lastSQL() . " " . $msg;
    $exception = new PDOException($err_msg, (int) $e->getCode());
    throw $exception;
    }
    }
    if ($this->log) {
    $message = sprintf("%s|%s", $query, implode(',', $this->parameters));
    comm_log($this->logName, $message);
    }
    $this->parameters = array();
    }
  324.  
  325. /**
    * 绑定
    *
    * @param string $para
    * @param string $value
    */
    public function bind($para, $value)
    {
    if (is_string($para)) {
    $this->parameters[sizeof($this->parameters)] = ":" . $para . "\x7F" . $value;
    } else {
    $this->parameters[sizeof($this->parameters)] = $para . "\x7F" . $value;
    }
    }
  326.  
  327. /**
    * 绑定多个
    *
    * @param array $parray
    */
    public function bindMore($parray)
    {
    if (empty($this->parameters) && is_array($parray)) {
    $columns = array_keys($parray);
    foreach ($columns as $i => &$column) {
    $this->bind($column, $parray[$column]);
    }
    }
    }
  328.  
  329. /**
    * 执行 SQL
    *
    * @param string $query
    * @param array $params
    * @param int $fetchmode
    * @return mixed
    */
    public function query($query = '', $params = null, $fetchmode = PDO::FETCH_ASSOC)
    {
    $query = trim($query);
    if (empty($query)) {
    $query = $this->build();
    if (!$params) {
    $params = $this->getBindValues();
    }
    } else {
    $this->parseType($query);
    }
    $this->resetAll();
    $this->lastSql = $query;
    if ($this->type == 'SELECT' && $this->mem) {
    if (empty($this->memKey)) {
    $this->memKey = $query . ' [' . implode(',', $params) . ']';
    }
  330.  
  331. $buf = $this->mem->get($this->memKey);
    if ($buf !== false) {
    $this->resetMem();
    return $buf;
    }
    }
    $this->execute($query, $params);
    $rawStatement = explode(" ", $query);
    $statement = strtolower(trim($rawStatement[0]));
    if ($statement === 'select' || $statement === 'show') {
    $rs = $this->sQuery->fetchAll($fetchmode);
    if ($statement === 'select' && $this->mem) {
    $this->mem->set($this->memKey, $rs, 0, $this->memTime);
    $this->resetMem();
    }
    return $rs;
    } elseif ($statement === 'update' || $statement === 'delete') {
    return $this->sQuery->rowCount();
    } elseif ($statement === 'insert') {
    if ($this->sQuery->rowCount() > 0) {
    return $this->lastInsertId();
    }
    } else {
    return null;
    }
  332.  
  333. return null;
    }
  334.  
  335. /**
    * 返回一列
    *
    * @param string $query
    * @param array $params
    * @return array
    */
    public function column($query = '', $params = null)
    {
    $query = trim($query);
    if (empty($query)) {
    $query = $this->build();
    if (!$params) {
    $params = $this->getBindValues();
    }
    }
    $this->resetAll();
    $this->lastSql = $query;
    if ($this->mem) {
    if (empty($this->memKey)) {
    $this->memKey = $query . ' [' . implode(',', $params) . ']';
    }
  336.  
  337. $buf = $this->mem->get($this->memKey);
    if ($buf !== false) {
    $this->resetMem();
    return $buf;
    }
    }
    if (empty($this->type)) {
    $this->parseType($query);
    }
    $this->execute($query, $params);
    $columns = $this->sQuery->fetchAll(PDO::FETCH_NUM);
    $column = null;
    foreach ($columns as $cells) {
    $column[] = $cells[0];
    }
    if ($this->mem) {
    $this->mem->set($this->memKey, $column, 0, $this->memTime);
    $this->resetMem();
    }
    return $column;
    }
  338.  
  339. /**
    * 返回一行
    *
    * @param string $query
    * @param array $params
    * @param int $fetchmode
    * @return array
    */
    public function row($query = '', $params = null, $fetchmode = PDO::FETCH_ASSOC)
    {
    $query = trim($query);
    if (empty($query)) {
    $query = $this->build();
    if (!$params) {
    $params = $this->getBindValues();
    }
    }
  340.  
  341. $this->resetAll();
    $this->lastSql = $query;
    if ($this->mem) {
    if (empty($this->memKey)) {
    $this->memKey = $query . ' [' . implode(',', $params) . ']';
    }
    $buf = $this->mem->get($this->memKey);
    if ($buf !== false) {
    $this->resetMem();
    return $buf;
    }
    }
    if (empty($this->type)) {
    $this->parseType($query);
    }
    $this->execute($query, $params);
    $rs = $this->sQuery->fetch($fetchmode);
    if ($this->mem) {
    $this->mem->set($this->memKey, $rs, 0, $this->memTime);
    $this->resetMem();
    }
    return $rs;
    }
  342.  
  343. /**
    * 返回单个值
    *
    * @param string $query
    * @param array $params
    * @return string
    */
    public function single($query = '', $params = null)
    {
    $query = trim($query);
    if (empty($query)) {
    $query = $this->build();
    if (!$params) {
    $params = $this->getBindValues();
    }
    }
    $this->resetAll();
    if ($this->mem) {
    if (empty($this->memKey)) {
    $this->memKey = $query . ' [' . implode(',', $params) . ']';
    }
    $buf = $this->mem->get($this->memKey);
    if ($buf !== false) {
    $this->resetMem();
    return $buf;
    }
    }
    if (empty($this->type)) {
    $this->parseType($query);
    }
    $this->execute($query, $params);
    $rs = $this->sQuery->fetchColumn();
    if ($this->mem) {
    $this->mem->set($this->memKey, $rs, 0, $this->memTime);
    $this->resetMem();
    }
    return $rs;
    }
  344.  
  345. /**
    * 返回 lastInsertId
    *
    * @return string
    */
    public function lastInsertId()
    {
    return $this->pdo->lastInsertId();
    }
  346.  
  347. /**
    * 返回最后一条执行的 sql
    *
    * @return string
    */
    public function lastSQL()
    {
    return $this->lastSql;
    }
  348.  
  349. /**
    * 开始事务
    */
    public function beginTrans()
    {
    try {
    return $this->pdo->beginTransaction();
    } catch (PDOException $e) {
    // 服务端断开时重连一次
    if ($e->errorInfo[1] == 2006 || $e->errorInfo[1] == 2013) {
    $this->closeConnection();
    $this->connect();
    return $this->pdo->beginTransaction();
    } else {
    throw $e;
    }
    }
    }
  350.  
  351. /**
    * 提交事务
    */
    public function commitTrans()
    {
    return $this->pdo->commit();
    }
  352.  
  353. /**
    * 事务回滚
    */
    public function rollBackTrans()
    {
    if ($this->pdo) {
    if ($this->pdo->inTransaction()) {
    return $this->pdo->rollBack();
    }
    }
    return true;
    }
  354.  
  355. /**
    * hash分表
    */
    protected function hashTable($pre, $salt)
    {
    if (empty($salt)) {
    return $pre . '0';
    }
  356.  
  357. $salt = strtolower($salt);
    if (is_numeric($salt) && strlen($salt) > 1) {
    $hash = substr($salt, -2, 2);
    } else if (preg_match("/^[0-9a-z]{1}$/", substr($salt, -1, 1))) {
    $hash = substr($salt, -1, 1);
    } else {
    return $pre . '0';
    }
    return $pre . $hash;
    }
  358.  
  359. public function log($logName = '')
    {
    $this->log = true;
    if (!empty($logName)) {
    $this->logName = $logName;
    }
    return $this;
    }
  360.  
  361. /**
    * 没有设置type,也不是select(),update(),insert(),delete()方法,则分析sql语句,设置type
    */
    public function parseType($query)
    {
    $query = trim($query);
    if (empty($query)) {
    $this->type = 'SELECT';
    }
    $this->type = strtoupper(explode(' ', $query)[0]);
    }
    /**
    * (废弃,已自动判断)
    * SELECT:读库
    * 其他:写库
    */
    public function setType($type) {
    $this->type = strtoupper($type);
    }
    }

PDO连接数据库-Xmodel的更多相关文章

  1. 【转】php pdo连接数据库 解决中文乱码问题(wordpress mysql 问号?? ??)

    原文链接:http://blog.csdn.net/ysydao/article/details/11002295 PHP 用pdo连接数据库时出现中文乱码问题解决办法 1.array(PDO::MY ...

  2. PDO连接数据库

    PDO连接数据库 PDO简介和配置 php.ini extension=php_pdo.dll extension=php_pdo_myysql.dll PDO连接MYSQL new PDO(&quo ...

  3. 使用PDO连接数据库 查询和插入乱码的解决方法

    问题:PDO连接数据库后,查询和插入中文到数据库,出现乱码,如图: 解决方法: 法1: try{ $opts_values = array(PDO::MYSQL_ATTR_INIT_COMMAND=& ...

  4. PHP5中使用PDO连接数据库的方法

    PDO(PHP Data Object) 是PHP 中加入的东西,是PHP 5新加入的一个重大功能,因为在PHP 5以前的php4/php3都是一堆的数据库扩展来跟各个数据库的连接和处理,php_my ...

  5. php PDO连接数据库

    [PDO是啥] PDO是PHP 5新加入的一个重大功能,因为在PHP 5以前的php4/php3都是一堆的数据库扩展来跟各个数据库的连接和处理,什么 php_mysql.dll.php_pgsql.d ...

  6. php+mysql+pdo连接数据库

    1.$pdo = new PDO("mysql:host=localhost;dbname=test","root","123456");/ ...

  7. 封装PDO连接数据库代码

    废话不说直接上代码: <?php class DB { protected static $_connect; protected $dsn, $pdo; protected $_data, $ ...

  8. 使用PDO连接数据库

    PDO(PHP数据对象) 是一个轻量级的.具有兼容接口的PHP数据连接拓展,是一个PHP官方的PECL库,随PHP 5.1发布,需要PHP 5的面向对象支持,因而在更早的版本上无法使用.它所提供的数据 ...

  9. pdo 连接数据库 报错 could not find driver 解决方法

    在windows 下,调试一个PHP程序时,报了这个错误, could not find driver 原来我的这个程序中用到了PDO对象, 连接mysql 5.  在PHP的默认设置中,只打开了ph ...

随机推荐

  1. history.go(-1)和History.back()的区别

    简单的说就是:go(-1): 返回上一页,原页面表单中的内容会丢失:back(-1): 返回上一页,原页表表单中的内容会保留,一般还是back(-1)用的多

  2. MySQL 数据库-索引注意事项

        索引注意事项 (1)最左前缀原则 如果查询的时候,查询条件精确匹配索引的左边连续一列或几列,则可以命中索引. (2)避免where 子句中对字段施加函数,如to_date(create_tim ...

  3. Initialize a vector in C++ (5 different ways)

    https://www.geeksforgeeks.org/initialize-a-vector-in-cpp-different-ways/ Following are different way ...

  4. WPF双向数据绑定总结

    参考官方:https://docs.microsoft.com/zh-cn/dotnet/framework/wpf/data/data-binding-wpf 实例程序:https://files. ...

  5. C# System.IO.StreamReader

    实现一个 TextReader,使其以一种特定的编码从字节流中读取字符. using System; using System.IO; class Test { public static void ...

  6. idea java9以及以上 出现找不到class的情况

    https://juejin.im/entry/59cdb7e65188255d3448fc64 https://blog.jetbrains.com/idea/2017/03/support-for ...

  7. 在windows命令行批量ping局域网内IP

    参考了博客园Alfred Zhao的文章<Windows平台ping测试局域网所有在用IP> 在cmd命令行运行如下命令即可: ,,) -w .%i | find "回复&quo ...

  8. 【VS2019】F12跳转到源码,关闭浏览器不停止项目【转】

    [VS2019]F12跳转到源码 1.工具->选项 2.文本编辑器->C#->高级->勾选支持导航到反编译源码 3.关闭浏览器不停止项目

  9. Saltstack之Scheduler

    一.引言: 在日常的运维工作中经常会遇到需要定时定点启动任务,首先会考虑到crontab,但是通过crontab的话需要每台机器下进行设置,这样统一管理的话比较复杂:通过查百度和google发现sal ...

  10. system generator学习笔记【01】

    作者:桂. 时间:2018-05-18  18:26:50 链接:http://www.cnblogs.com/xingshansi/p/9045914.html 前言 学习使用system gene ...