diff --git a/library/think/Model.php b/library/think/Model.php index a432b57d..71f8bb17 100644 --- a/library/think/Model.php +++ b/library/think/Model.php @@ -199,7 +199,7 @@ class Model throw new Exception(' fields not exists :[' . $key . '=>' . $val . ']'); } unset($data[$key]); - } elseif (is_scalar($val) && empty($this->options['bind'][':' . $key])) { + } elseif (is_scalar($val) && empty($this->options['bind'][$key])) { // 字段类型检查 $this->_parseType($data, $key, $this->options['bind']); } @@ -779,7 +779,7 @@ class Model foreach ($options['where'] as $key => $val) { $key = trim($key); if (in_array($key, $fields, true)) { - if (is_scalar($val) && empty($options['bind'][':' . $key])) { + if (is_scalar($val) && empty($options['bind'][$key])) { $this->_parseType($options['where'], $key, $options['bind']); } } @@ -804,19 +804,19 @@ class Model */ protected function _parseType(&$data, $key, &$bind) { - if (!isset($bind[':' . $key]) && isset($this->fields['_type'][$key])) { + if (!isset($bind[$key]) && isset($this->fields['_type'][$key])) { $fieldType = strtolower($this->fields['_type'][$key]); if (false !== strpos($fieldType, 'enum')) { // 支持ENUM类型优先检测 } elseif (false === strpos($fieldType, 'bigint') && false !== strpos($fieldType, 'int')) { - $bind[':' . $key] = [$data[$key], \PDO::PARAM_INT]; - $data[$key] = ':' . $key; + $bind[$key] = [$data[$key], \PDO::PARAM_INT]; + $data[$key] = ':' . $key; } elseif (false !== strpos($fieldType, 'float') || false !== strpos($fieldType, 'double')) { - $bind[':' . $key] = [$data[$key], \PDO::PARAM_INT]; - $data[$key] = ':' . $key; + $bind[$key] = [$data[$key], \PDO::PARAM_INT]; + $data[$key] = ':' . $key; } elseif (false !== strpos($fieldType, 'bool')) { - $bind[':' . $key] = [$data[$key], \PDO::PARAM_BOOL]; - $data[$key] = ':' . $key; + $bind[$key] = [$data[$key], \PDO::PARAM_BOOL]; + $data[$key] = ':' . $key; } elseif (false !== strpos($fieldType, 'json') && is_array($data[$key])) { $data[$key] = json_encode($data[$key]); } diff --git a/library/think/db/Driver.php b/library/think/db/Driver.php index 83304393..5fc0a8f0 100644 --- a/library/think/db/Driver.php +++ b/library/think/db/Driver.php @@ -168,14 +168,8 @@ abstract class Driver } $this->queryStr = $str; - if (!empty($bind)) { - $that = $this; - $this->queryStr = strtr($this->queryStr, array_map(function ($val) use ($that) { - return $that->quote(is_array($val) ? $val[0] : $val); - }, $bind)); - } if ($fetchSql) { - return $this->queryStr; + return $this->getBindSql($this->queryStr, $bind); } //释放前次的查询结果 if (!empty($this->PDOStatement)) { @@ -183,33 +177,20 @@ abstract class Driver } Db::$queryTimes++; - // 调试开始 - $this->debug(true); - $this->PDOStatement = $this->_linkID->prepare($str); - if (false === $this->PDOStatement) { - $this->error(); - return false; - } - foreach ($bind as $key => $val) { - if (is_array($val)) { - $this->PDOStatement->bindValue($key, $val[0], $val[1]); - } else { - $this->PDOStatement->bindValue($key, $val); - } - } try { + // 调试开始 + $this->debug(true); + // 预处理 + $this->PDOStatement = $this->_linkID->prepare($str); + // 参数绑定 + $this->bindValue($bind); + // 执行查询 $result = $this->PDOStatement->execute(); // 调试结束 $this->debug(false); - if (false === $result) { - $this->error(); - return false; - } else { - return $this->getResult(); - } + return $this->getResult(); } catch (\PDOException $e) { - $this->error(); - return false; + throw new Exception($e->getMessage()); } } @@ -229,14 +210,8 @@ abstract class Driver } $this->queryStr = $str; - if (!empty($bind)) { - $that = $this; - $this->queryStr = strtr($this->queryStr, array_map(function ($val) use ($that) { - return $that->quote(is_array($val) ? $val[0] : $val); - }, $bind)); - } if ($fetchSql) { - return $this->queryStr; + return $this->getBindSql($this->queryStr, $bind); } //释放前次的查询结果 if (!empty($this->PDOStatement)) { @@ -244,36 +219,66 @@ abstract class Driver } Db::$executeTimes++; - // 记录开始执行时间 - $this->debug(true); - $this->PDOStatement = $this->_linkID->prepare($str); - if (false === $this->PDOStatement) { - $this->error(); - return false; - } - foreach ($bind as $key => $val) { - if (is_array($val)) { - $this->PDOStatement->bindValue($key, $val[0], $val[1]); - } else { - $this->PDOStatement->bindValue($key, $val); - } - } try { + // 调试开始 + $this->debug(true); + // 预处理 + $this->PDOStatement = $this->_linkID->prepare($str); + // 参数绑定操作 + $this->bindValue($bind); + // 执行语句 $result = $this->PDOStatement->execute(); + // 调试结束 $this->debug(false); - if (false === $result) { - $this->error(); - return false; - } else { - $this->numRows = $this->PDOStatement->rowCount(); - if (preg_match("/^\s*(INSERT\s+INTO|REPLACE\s+INTO)\s+/i", $str)) { - $this->lastInsID = $this->_linkID->lastInsertId(); - } - return $this->numRows; + + $this->numRows = $this->PDOStatement->rowCount(); + if (preg_match("/^\s*(INSERT\s+INTO|REPLACE\s+INTO)\s+/i", $str)) { + $this->lastInsID = $this->_linkID->lastInsertId(); } + return $this->numRows; } catch (\PDOException $e) { - $this->error(); - return false; + throw new Exception($e->getMessage()); + } + } + + protected function getBindSql($sql, array $bind = []) + { + if ($bind) { + foreach ($bind as $key => $val) { + // 占位符 + $val = is_array($val) ? $val[0] : $val; + if (is_numeric($key)) { + // 问号占位符 + $sql = substr_replace($sql, $val, strpos($sql, '?'), 1); + } else { + $sql = str_replace(':' . $key, $val, $sql); + } + } + } + return $sql; + } + + /** + * 参数绑定 + * 支持 ['name'=>'value','id'=>123] 对应命名占位符 + * 或者 ['value',123] 对应问号占位符 + * @access public + * @param array $bind 要绑定的参数列表 + * @return void + */ + protected function bindValue(array $bind = []) + { + foreach ($bind as $key => $val) { + // 占位符 + $param = is_numeric($key) ? $key + 1 : ':' . $key; + if (is_array($val)) { + $result = $this->PDOStatement->bindValue($param, $val[0], $val[1]); + } else { + $result = $this->PDOStatement->bindValue($param, $val); + } + if (!$result) { + throw new Exception('bind param error : [ ' . $param . '=>' . $val . ' ]'); + } } } @@ -305,11 +310,11 @@ abstract class Driver public function commit() { if ($this->transTimes > 0) { - $result = $this->_linkID->commit(); - $this->transTimes = 0; - if (!$result) { - $this->error(); - return false; + try { + $result = $this->_linkID->commit(); + $this->transTimes = 0; + } catch (\PDOException $e) { + throw new Exception($e->getMessage()); } } return true; @@ -323,11 +328,11 @@ abstract class Driver public function rollback() { if ($this->transTimes > 0) { - $result = $this->_linkID->rollback(); - $this->transTimes = 0; - if (!$result) { - $this->error(); - return false; + try { + $result = $this->_linkID->rollback(); + $this->transTimes = 0; + } catch (\PDOException $e) { + throw new Exception($e->getMessage()); } } return true; @@ -376,33 +381,6 @@ abstract class Driver $this->_linkID = null; } - /** - * 数据库错误信息 - * 并显示当前的SQL语句 - * @access public - * @return string - */ - public function error() - { - if ($this->PDOStatement) { - $error = $this->PDOStatement->errorInfo(); - $this->error = $error[1] . ':' . $error[2]; - } else { - $this->error = ''; - } - if ('' != $this->queryStr) { - $this->error .= "\n [ SQL语句 ] : " . $this->queryStr; - } - // 记录错误日志 - Log::record($this->error, 'error'); - if ($this->config['debug']) { - // 开启数据库调试模式 - throw new Exception($this->error); - } else { - return $this->error; - } - } - /** * 设置锁机制 * @access protected @@ -428,12 +406,12 @@ abstract class Driver $set[] = $this->parseKey($key) . '=NULL'; } elseif (is_scalar($val)) { // 过滤非标量数据 - if (0 === strpos($val, ':') && in_array($val, array_keys($this->bind))) { + if (0 === strpos($val, ':') && isset($this->bind[substr($val, 1)])) { $set[] = $this->parseKey($key) . '=' . $val; } else { $name = count($this->bind); - $set[] = $this->parseKey($key) . '=:' . $_SERVER['REQUEST_TIME'] . '_' . $name; - $this->bindParam($_SERVER['REQUEST_TIME'] . '_' . $name, $val); + $set[] = $this->parseKey($key) . '=:' . $key . $_SERVER['REQUEST_TIME'] . '_' . $name; + $this->bindParam($key . $_SERVER['REQUEST_TIME'] . '_' . $name, $val); } } } @@ -449,7 +427,7 @@ abstract class Driver */ protected function bindParam($name, $value) { - $this->bind[':' . $name] = $value; + $this->bind[$name] = $value; } /** @@ -486,7 +464,7 @@ abstract class Driver protected function parseValue($value) { if (is_string($value)) { - $value = strpos($value, ':') === 0 && in_array($value, array_keys($this->bind)) ? $value : $this->quote($value); + $value = strpos($value, ':') === 0 && isset($this->bind[substr($value, 1)]) ? $value : $this->quote($value); } elseif (isset($value[0]) && is_string($value[0]) && strtolower($value[0]) == 'exp') { $value = $this->quote($value[1]); } elseif (is_array($value)) { @@ -926,8 +904,8 @@ abstract class Driver $values[] = $val; } else { $name = count($this->bind); - $values[] = ':' . $_SERVER['REQUEST_TIME'] . '_' . $name; - $this->bindParam($_SERVER['REQUEST_TIME'] . '_' . $name, $val); + $values[] = ':' . $key . $_SERVER['REQUEST_TIME'] . '_' . $name; + $this->bindParam($key . $_SERVER['REQUEST_TIME'] . '_' . $name, $val); } } } @@ -968,8 +946,8 @@ abstract class Driver $value[] = $val; } else { $name = count($this->bind); - $value[] = ':' . $_SERVER['REQUEST_TIME'] . '_' . $name; - $this->bindParam($_SERVER['REQUEST_TIME'] . '_' . $name, $val); + $value[] = ':' . $key . $_SERVER['REQUEST_TIME'] . '_' . $name; + $this->bindParam($key . $_SERVER['REQUEST_TIME'] . '_' . $name, $val); } } } @@ -1149,7 +1127,16 @@ abstract class Driver */ public function getError() { - return $this->error; + if ($this->PDOStatement) { + $error = $this->PDOStatement->errorInfo(); + $error = $error[1] . ':' . $error[2]; + } else { + $error = ''; + } + if ('' != $this->queryStr) { + $error .= "\n [ SQL语句 ] : " . $this->queryStr; + } + return $error; } /** diff --git a/library/think/db/driver/Mongo.php b/library/think/db/driver/Mongo.php index 0335035d..75897767 100644 --- a/library/think/db/driver/Mongo.php +++ b/library/think/db/driver/Mongo.php @@ -14,7 +14,6 @@ namespace think\db\driver; use think\db\Driver; use think\Exception; use think\Lang; -use think\Log; /** * Mongo数据库驱动 @@ -69,7 +68,7 @@ class Mongo extends Driver $host = 'mongodb://' . ($config['username'] ? "{$config['username']}" : '') . ($config['password'] ? ":{$config['password']}@" : '') . $config['hostname'] . ($config['hostport'] ? ":{$config['hostport']}" : '') . '/' . ($config['database'] ? "{$config['database']}" : ''); try { - $this->linkID[$linkNum] = new \mongoClient($host, !empty($this->config['params'])?$this->config['params']:array()); + $this->linkID[$linkNum] = new \mongoClient($host, !empty($this->config['params']) ? $this->config['params'] : array()); } catch (\MongoConnectionException $e) { throw new Exception($e->getmessage()); } @@ -94,7 +93,7 @@ class Mongo extends Driver $this->initConnect($master); } - $db = $db?$db:$this->config['database']; + $db = $db ? $db : $this->config['database']; try { if (!empty($db)) { @@ -191,11 +190,10 @@ class Mongo extends Driver * @access public * @return string */ - public function error() + public function getError() { - $this->error = $this->_mongo->lastError(); - Log::record($this->error, 'error'); - return $this->error; + $error = $this->_mongo->lastError(); + return $error; } /** @@ -482,8 +480,8 @@ class Mongo extends Driver } $this->model = $options['model']; $this->queryTimes++; - $query = $this->parseWhere(!empty($options['where'])?$options['where']:''); - $fields = $this->parseField(!empty($options['field'])?$options['field']:''); + $query = $this->parseWhere(!empty($options['where']) ? $options['where'] : ''); + $fields = $this->parseField(!empty($options['field']) ? $options['field'] : ''); if ($this->config['debug']) { $this->queryStr = $this->_dbName . '.' . $this->_collectionName . '.findOne('; $this->queryStr .= $query ? json_encode($query) : '{}'; @@ -637,7 +635,7 @@ class Mongo extends Driver */ protected function parseOrder($order) { - if(is_array($order)) { + if (is_array($order)) { $order = join(',', $order); } if (is_string($order)) { @@ -742,14 +740,14 @@ class Mongo extends Driver { $query = []; switch ($key) { - case '_query': // 字符串模式查询条件 + case '_query': // 字符串模式查询条件 parse_str($val, $query); if (isset($query['_logic']) && strtolower($query['_logic']) == 'or') { unset($query['_logic']); $query['$or'] = $query; } break; - case '_string': // MongoCode查询 + case '_string': // MongoCode查询 $query['$where'] = new \MongoCode($val); break; } diff --git a/library/think/db/driver/Oracle.php b/library/think/db/driver/Oracle.php index 5478a342..5ab0f083 100644 --- a/library/think/db/driver/Oracle.php +++ b/library/think/db/driver/Oracle.php @@ -11,6 +11,7 @@ namespace think\db\driver; +use think\Db; use think\db\Driver; /** @@ -64,30 +65,20 @@ class Oracle extends Driver $this->free(); } - $this->executeTimes++; - // 记录开始执行时间 - $this->debug(true); - $this->PDOStatement = $this->_linkID->prepare($str); - if (false === $this->PDOStatement) { - $this->error(); - return false; - } + Db::$executeTimes++; try { - $result = $this->PDOStatement->execute($bind); + // 记录开始执行时间 + $this->debug(true); + $this->PDOStatement = $this->_linkID->prepare($str); + $result = $this->PDOStatement->execute($bind); $this->debug(false); - if (false === $result) { - $this->error(); - return false; - } else { - $this->numRows = $this->PDOStatement->rowCount(); - if ($flag || preg_match("/^\s*(INSERT\s+INTO|REPLACE\s+INTO)\s+/i", $str)) { - $this->lastInsID = $this->_linkID->lastInsertId(); - } - return $this->numRows; + $this->numRows = $this->PDOStatement->rowCount(); + if ($flag || preg_match("/^\s*(INSERT\s+INTO|REPLACE\s+INTO)\s+/i", $str)) { + $this->lastInsID = $this->_linkID->lastInsertId(); } + return $this->numRows; } catch (\PDOException $e) { - $this->error(); - return false; + throw new Exception($e->getMessage()); } }