From 109cf819be5aca6b28d7dd6d66e381017f6dd598 Mon Sep 17 00:00:00 2001 From: molong Date: Sat, 14 Jan 2017 11:07:28 +0800 Subject: [PATCH] =?UTF-8?q?=E5=86=85=E6=A0=B8=E6=9B=B4=E6=96=B0?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- core/convention.php | 2 + core/library/think/Model.php | 10 +- core/library/think/Route.php | 2 +- core/library/think/Session.php | 7 +- core/library/think/Validate.php | 4 +- core/library/think/cache/driver/File.php | 2 +- core/library/think/db/Builder.php | 2 +- core/library/think/db/Connection.php | 141 +++++++--- core/library/think/db/Query.php | 244 ++++++++++++++++-- .../think/model/relation/BelongsToMany.php | 2 +- 10 files changed, 336 insertions(+), 80 deletions(-) diff --git a/core/convention.php b/core/convention.php index a35ac0b9..c66ef583 100644 --- a/core/convention.php +++ b/core/convention.php @@ -203,6 +203,8 @@ return [ 'type' => '', // 是否自动开启 SESSION 'auto_start' => true, + 'httponly' => true, + 'secure' => true, ], // +---------------------------------------------------------------------- diff --git a/core/library/think/Model.php b/core/library/think/Model.php index b520f801..0491e551 100644 --- a/core/library/think/Model.php +++ b/core/library/think/Model.php @@ -438,7 +438,11 @@ abstract class Model implements \JsonSerializable, \ArrayAccess // 类型转换 $value = $this->readTransform($value, $this->type[$name]); } elseif (in_array($name, [$this->createTime, $this->updateTime])) { - $value = $this->formatDateTime($value, $this->dateFormat); + if (is_string($this->autoWriteTimestamp) && in_array(strtolower($this->autoWriteTimestamp), ['datetime', 'date', 'timestamp'])) { + $value = $this->formatDateTime(strtotime($value), $this->dateFormat); + } else { + $value = $this->formatDateTime($value, $this->dateFormat); + } } elseif ($notFound) { $method = Loader::parseName($name, 1, false); if (method_exists($this, $method) && $this->$method() instanceof Relation) { @@ -724,7 +728,7 @@ abstract class Model implements \JsonSerializable, \ArrayAccess $this->autoCompleteData($this->auto); // 自动写入更新时间 - if ($this->autoWriteTimestamp && $this->updateTime && !isset($this->data[$this->updateTime])) { + if ($this->autoWriteTimestamp && $this->updateTime && (empty($this->change) || !in_array($this->updateTime, $this->change))) { $this->setAttr($this->updateTime, null); } @@ -781,7 +785,7 @@ abstract class Model implements \JsonSerializable, \ArrayAccess $this->autoCompleteData($this->insert); // 自动写入创建时间 - if ($this->autoWriteTimestamp && $this->createTime && !isset($this->data[$this->createTime])) { + if ($this->autoWriteTimestamp && $this->createTime && (empty($this->change) || !in_array($this->createTime, $this->change))) { $this->setAttr($this->createTime, null); } diff --git a/core/library/think/Route.php b/core/library/think/Route.php index 4f08e911..1629d636 100644 --- a/core/library/think/Route.php +++ b/core/library/think/Route.php @@ -1097,7 +1097,7 @@ class Route * 绑定到模块/控制器 * @access public * @param string $url URL地址 - * @param string $class 控制器类名(带命名空间) + * @param string $controller 控制器类名(带命名空间) * @param string $depr URL分隔符 * @return array */ diff --git a/core/library/think/Session.php b/core/library/think/Session.php index 48f23caa..35726220 100644 --- a/core/library/think/Session.php +++ b/core/library/think/Session.php @@ -77,7 +77,12 @@ class Session ini_set('session.gc_maxlifetime', $config['expire']); ini_set('session.cookie_lifetime', $config['expire']); } - + if (isset($config['secure'])) { + ini_set('session.cookie_secure', $config['secure']); + } + if (isset($config['httponly'])) { + ini_set('session.cookie_httponly', $config['httponly']); + } if (isset($config['use_cookies'])) { ini_set('session.use_cookies', $config['use_cookies'] ? 1 : 0); } diff --git a/core/library/think/Validate.php b/core/library/think/Validate.php index e3bc9db6..e91ee338 100644 --- a/core/library/think/Validate.php +++ b/core/library/think/Validate.php @@ -1222,9 +1222,9 @@ class Validate $msg = Lang::get(substr($msg, 2, -1)); } - if (is_string($msg) && is_string($rule) && false !== strpos($msg, ':')) { + if (is_string($msg) && is_scalar($rule) && false !== strpos($msg, ':')) { // 变量替换 - if (strpos($rule, ',')) { + if (is_string($rule) && strpos($rule, ',')) { $array = array_pad(explode(',', $rule), 3, ''); } else { $array = array_pad([], 3, ''); diff --git a/core/library/think/cache/driver/File.php b/core/library/think/cache/driver/File.php index 6f52693b..dba02c3e 100644 --- a/core/library/think/cache/driver/File.php +++ b/core/library/think/cache/driver/File.php @@ -21,7 +21,7 @@ class File extends Driver { protected $options = [ 'expire' => 0, - 'cache_subdir' => false, + 'cache_subdir' => true, 'prefix' => '', 'path' => CACHE_PATH, 'data_compress' => false, diff --git a/core/library/think/db/Builder.php b/core/library/think/db/Builder.php index 2372152c..3e7a60e9 100644 --- a/core/library/think/db/Builder.php +++ b/core/library/think/db/Builder.php @@ -316,7 +316,7 @@ abstract class Builder throw new Exception('where express error:' . $exp); } } - $bindName = $bindName ?: 'where_' . str_replace('.', '_', $field); + $bindName = $bindName ?: 'where_' . str_replace(['.', '-'], '_', $field); if (preg_match('/\W/', $bindName)) { // 处理带非单词字符的字段名 $bindName = md5($bindName); diff --git a/core/library/think/db/Connection.php b/core/library/think/db/Connection.php index ef56c6fd..4e18f812 100644 --- a/core/library/think/db/Connection.php +++ b/core/library/think/db/Connection.php @@ -95,6 +95,8 @@ abstract class Connection 'slave_no' => '', // 是否严格检查字段是否存在 'fields_strict' => true, + // 数据返回类型 + 'result_type' => PDO::FETCH_ASSOC, // 数据集返回类型 'resultset_type' => 'array', // 自动写入时间戳字段 @@ -118,6 +120,9 @@ abstract class Connection PDO::ATTR_EMULATE_PREPARES => false, ]; + // 绑定参数 + protected $bind = []; + /** * 架构函数 读取数据库配置信息 * @access public @@ -269,6 +274,10 @@ abstract class Connection if (isset($config['resultset_type'])) { $this->resultSetType = $config['resultset_type']; } + // 数据返回类型 + if (isset($config['result_type'])) { + $this->fetchType = $config['result_type']; + } try { if (empty($config['dsn'])) { $config['dsn'] = $this->parseDsn($config); @@ -319,22 +328,30 @@ abstract class Connection /** * 执行查询 返回数据集 * @access public + * @param string $sql sql指令 + * @param array $bind 参数绑定 + * @param bool $master 是否在主服务器读操作 + * @param bool $class 是否返回PDO对象 * @param string $sql sql指令 * @param array $bind 参数绑定 * @param boolean $master 是否在主服务器读操作 - * @param bool|string $class 指定返回的数据集对象 + * @param bool $pdo 是否返回PDO对象 * @return mixed * @throws BindParamException * @throws PDOException */ - public function query($sql, $bind = [], $master = false, $class = false) + public function query($sql, $bind = [], $master = false, $pdo = false) { $this->initConnect($master); if (!$this->linkID) { return false; } - // 根据参数绑定组装最终的SQL语句 - $this->queryStr = $this->getRealSql($sql, $bind); + + // 记录SQL语句 + $this->queryStr = $sql; + if ($bind) { + $this->bind = $bind; + } //释放前次的查询结果 if (!empty($this->PDOStatement) && $this->PDOStatement->queryString != $sql) { @@ -349,16 +366,22 @@ abstract class Connection if (empty($this->PDOStatement)) { $this->PDOStatement = $this->linkID->prepare($sql); } + // 是否为存储过程调用 + $procedure = in_array(strtolower(substr(trim($sql), 0, 4)), ['call', 'exec']); // 参数绑定 - $this->bindValue($bind); + if ($procedure) { + $this->bindParam($bind); + } else { + $this->bindValue($bind); + } // 执行查询 $this->PDOStatement->execute(); // 调试结束 $this->debug(false); - $procedure = in_array(strtolower(substr(trim($sql), 0, 4)), ['call', 'exec']); - return $this->getResult($class, $procedure); + // 返回结果集 + return $this->getResult($pdo, $procedure); } catch (\PDOException $e) { - throw new PDOException($e, $this->config, $this->queryStr); + throw new PDOException($e, $this->config, $this->getLastsql()); } } @@ -377,8 +400,12 @@ abstract class Connection if (!$this->linkID) { return false; } - // 根据参数绑定组装最终的SQL语句 - $this->queryStr = $this->getRealSql($sql, $bind); + + // 记录SQL语句 + $this->queryStr = $sql; + if ($bind) { + $this->bind = $bind; + } //释放前次的查询结果 if (!empty($this->PDOStatement) && $this->PDOStatement->queryString != $sql) { @@ -393,8 +420,14 @@ abstract class Connection if (empty($this->PDOStatement)) { $this->PDOStatement = $this->linkID->prepare($sql); } - // 参数绑定操作 - $this->bindValue($bind); + // 是否为存储过程调用 + $procedure = in_array(strtolower(substr(trim($sql), 0, 4)), ['call', 'exec']); + // 参数绑定 + if ($procedure) { + $this->bindParam($bind); + } else { + $this->bindValue($bind); + } // 执行语句 $this->PDOStatement->execute(); // 调试结束 @@ -403,7 +436,7 @@ abstract class Connection $this->numRows = $this->PDOStatement->rowCount(); return $this->numRows; } catch (\PDOException $e) { - throw new PDOException($e, $this->config, $this->queryStr); + throw new PDOException($e, $this->config, $this->getLastsql()); } } @@ -416,23 +449,21 @@ abstract class Connection */ public function getRealSql($sql, array $bind = []) { - if ($bind) { - foreach ($bind as $key => $val) { - $value = is_array($val) ? $val[0] : $val; - $type = is_array($val) ? $val[1] : PDO::PARAM_STR; - if (PDO::PARAM_STR == $type) { - $value = $this->quote($value); - } elseif (PDO::PARAM_INT == $type) { - $value = (float) $value; - } - // 判断占位符 - $sql = is_numeric($key) ? - substr_replace($sql, $value, strpos($sql, '?'), 1) : - str_replace( - [':' . $key . ')', ':' . $key . ',', ':' . $key . ' '], - [$value . ')', $value . ',', $value . ' '], - $sql . ' '); + foreach ($bind as $key => $val) { + $value = is_array($val) ? $val[0] : $val; + $type = is_array($val) ? $val[1] : PDO::PARAM_STR; + if (PDO::PARAM_STR == $type) { + $value = $this->quote($value); + } elseif (PDO::PARAM_INT == $type) { + $value = (float) $value; } + // 判断占位符 + $sql = is_numeric($key) ? + substr_replace($sql, $value, strpos($sql, '?'), 1) : + str_replace( + [':' . $key . ')', ':' . $key . ',', ':' . $key . ' '], + [$value . ')', $value . ',', $value . ' '], + $sql . ' '); } return rtrim($sql); } @@ -444,7 +475,7 @@ abstract class Connection * @access public * @param array $bind 要绑定的参数列表 * @return void - * @throws \think\Exception + * @throws BindParamException */ protected function bindValue(array $bind = []) { @@ -463,7 +494,34 @@ abstract class Connection throw new BindParamException( "Error occurred when binding parameters '{$param}'", $this->config, - $this->queryStr, + $this->getLastsql(), + $bind + ); + } + } + } + + /** + * 存储过程的输入输出参数绑定 + * @access public + * @param array $bind 要绑定的参数列表 + * @return void + * @throws BindParamException + */ + protected function bindParam($bind) + { + foreach ($bind as $key => $val) { + if (is_numeric($key)) { + $key = $key + 1; + } + array_unshift($val, $key); + $result = call_user_func_array([$this->PDOStatement, 'bindParam'], $val); + if (!$result) { + $param = array_shift($val); + throw new BindParamException( + "Error occurred when binding parameters '{$param}'", + $this->config, + $this->getLastsql(), $bind ); } @@ -473,19 +531,19 @@ abstract class Connection /** * 获得数据集 * @access protected - * @param bool|string $class true 返回PDOStatement 字符串用于指定返回的类名 - * @param bool $procedure 是否存储过程 + * @param bool $pdo 是否返回PDOStatement + * @param bool $procedure 是否存储过程 * @return mixed */ - protected function getResult($class = '', $procedure = false) + protected function getResult($pdo = false, $procedure = false) { - if (true === $class) { + if ($pdo) { // 返回PDOStatement对象处理 return $this->PDOStatement; } if ($procedure) { // 存储过程返回结果 - return $this->procedure($class); + return $this->procedure(); } $result = $this->PDOStatement->fetchAll($this->fetchType); $this->numRows = count($result); @@ -500,14 +558,13 @@ abstract class Connection /** * 获得存储过程数据集 * @access protected - * @param bool|string $class true 返回PDOStatement 字符串用于指定返回的类名 * @return array */ - protected function procedure($class) + protected function procedure() { $item = []; do { - $result = $this->getResult($class); + $result = $this->getResult(); if ($result) { $item[] = $result; } @@ -698,7 +755,7 @@ abstract class Connection */ public function getLastSql() { - return $this->queryStr; + return $this->getRealSql($this->queryStr, $this->bind); } /** @@ -736,7 +793,7 @@ abstract class Connection $error = ''; } if ('' != $this->queryStr) { - $error .= "\n [ SQL语句 ] : " . $this->queryStr; + $error .= "\n [ SQL语句 ] : " . $this->getLastsql(); } return $error; } @@ -771,7 +828,7 @@ abstract class Connection // 记录操作结束时间 Debug::remark('queryEndTime', 'time'); $runtime = Debug::getRangeTime('queryStartTime', 'queryEndTime'); - $sql = $sql ?: $this->queryStr; + $sql = $sql ?: $this->getLastsql(); $log = $sql . ' [ RunTime:' . $runtime . 's ]'; $result = []; // SQL性能分析 diff --git a/core/library/think/db/Query.php b/core/library/think/db/Query.php index 263565f9..24f5ce2a 100644 --- a/core/library/think/db/Query.php +++ b/core/library/think/db/Query.php @@ -409,7 +409,7 @@ class Query if (isset($this->options['field'])) { unset($this->options['field']); } - $pdo = $this->field($field)->fetchPdo(true)->find(); + $pdo = $this->field($field)->limit(1)->getPdo(); if (is_string($pdo)) { // 返回SQL语句 return $pdo; @@ -459,7 +459,7 @@ class Query if ($key && '*' != $field) { $field = $key . ',' . $field; } - $pdo = $this->field($field)->fetchPdo(true)->select(); + $pdo = $this->field($field)->getPdo(); if (is_string($pdo)) { // 返回SQL语句 return $pdo; @@ -522,7 +522,7 @@ class Query * @param string $field 字段名 * @return float|int */ - public function sum($field = '*') + public function sum($field) { return $this->value('SUM(' . $field . ') AS tp_sum', 0, true); } @@ -533,7 +533,7 @@ class Query * @param string $field 字段名 * @return mixed */ - public function min($field = '*') + public function min($field) { return $this->value('MIN(' . $field . ') AS tp_min', 0, true); } @@ -544,7 +544,7 @@ class Query * @param string $field 字段名 * @return mixed */ - public function max($field = '*') + public function max($field) { return $this->value('MAX(' . $field . ') AS tp_max', 0, true); } @@ -555,7 +555,7 @@ class Query * @param string $field 字段名 * @return float|int */ - public function avg($field = '*') + public function avg($field) { return $this->value('AVG(' . $field . ') AS tp_avg', 0, true); } @@ -972,6 +972,156 @@ class Query return $this; } + /** + * 指定Null查询条件 + * @access public + * @param mixed $field 查询字段 + * @param string $logic 查询逻辑 and or xor + * @return $this + */ + public function whereNull($field, $logic = 'AND') + { + $this->parseWhereExp($logic, $field, 'null', null); + return $this; + } + + /** + * 指定NotNull查询条件 + * @access public + * @param mixed $field 查询字段 + * @param string $logic 查询逻辑 and or xor + * @return $this + */ + public function whereNotNull($field, $logic = 'AND') + { + $this->parseWhereExp($logic, $field, 'notnull', null); + return $this; + } + + /** + * 指定Exists查询条件 + * @access public + * @param mixed $condition 查询条件 + * @param string $logic 查询逻辑 and or xor + * @return $this + */ + public function whereExists($condition, $logic = 'AND') + { + $this->options['where'][strtoupper($logic)][] = ['exists', $condition]; + return $this; + } + + /** + * 指定NotExists查询条件 + * @access public + * @param mixed $condition 查询条件 + * @param string $logic 查询逻辑 and or xor + * @return $this + */ + public function whereNotExists($condition, $logic = 'AND') + { + $this->options['where'][strtoupper($logic)][] = ['not exists', $condition]; + return $this; + } + + /** + * 指定In查询条件 + * @access public + * @param mixed $field 查询字段 + * @param mixed $condition 查询条件 + * @param string $logic 查询逻辑 and or xor + * @return $this + */ + public function whereIn($field, $condition, $logic = 'AND') + { + $this->parseWhereExp($logic, $field, 'in', $condition); + return $this; + } + + /** + * 指定NotIn查询条件 + * @access public + * @param mixed $field 查询字段 + * @param mixed $condition 查询条件 + * @param string $logic 查询逻辑 and or xor + * @return $this + */ + public function whereNotIn($field, $condition, $logic = 'AND') + { + $this->parseWhereExp($logic, $field, 'not in', $condition); + return $this; + } + + /** + * 指定Like查询条件 + * @access public + * @param mixed $field 查询字段 + * @param mixed $condition 查询条件 + * @param string $logic 查询逻辑 and or xor + * @return $this + */ + public function whereLike($field, $condition, $logic = 'AND') + { + $this->parseWhereExp($logic, $field, 'like', $condition); + return $this; + } + + /** + * 指定NotLike查询条件 + * @access public + * @param mixed $field 查询字段 + * @param mixed $condition 查询条件 + * @param string $logic 查询逻辑 and or xor + * @return $this + */ + public function whereNotLike($field, $condition, $logic = 'AND') + { + $this->parseWhereExp($logic, $field, 'not like', $condition); + return $this; + } + + /** + * 指定Between查询条件 + * @access public + * @param mixed $field 查询字段 + * @param mixed $condition 查询条件 + * @param string $logic 查询逻辑 and or xor + * @return $this + */ + public function whereBetween($field, $condition, $logic = 'AND') + { + $this->parseWhereExp($logic, $field, 'between', $condition); + return $this; + } + + /** + * 指定NotBetween查询条件 + * @access public + * @param mixed $field 查询字段 + * @param mixed $condition 查询条件 + * @param string $logic 查询逻辑 and or xor + * @return $this + */ + public function whereNotBetween($field, $condition, $logic = 'AND') + { + $this->parseWhereExp($logic, $field, 'not between', $condition); + return $this; + } + + /** + * 指定Exp查询条件 + * @access public + * @param mixed $field 查询字段 + * @param mixed $condition 查询条件 + * @param string $logic 查询逻辑 and or xor + * @return $this + */ + public function whereExp($field, $condition, $logic = 'AND') + { + $this->parseWhereExp($logic, $field, 'exp', $condition); + return $this; + } + /** * 分析查询表达式 * @access public @@ -984,6 +1134,7 @@ class Query */ protected function parseWhereExp($logic, $field, $op, $condition, $param = []) { + $logic = strtoupper($logic); if ($field instanceof \Closure) { $this->options['where'][$logic][] = is_string($op) ? [$op, $field] : $field; return; @@ -1003,20 +1154,23 @@ class Query // 数组批量查询 $where = $field; foreach ($where as $k => $val) { - $this->options['multi'][$k][] = $val; + $this->options['multi'][$logic][$k][] = $val; } } elseif ($field && is_string($field)) { // 字符串查询 - $where[$field] = ['null', '']; + $where[$field] = ['null', '']; + $this->options['multi'][$logic][$field][] = $where[$field]; } } elseif (is_array($op)) { $where[$field] = $param; } elseif (in_array(strtolower($op), ['null', 'notnull', 'not null'])) { // null查询 - $where[$field] = [$op, '']; + $where[$field] = [$op, '']; + $this->options['multi'][$logic][$field][] = $where[$field]; } elseif (is_null($condition)) { // 字段相等查询 - $where[$field] = ['eq', $op]; + $where[$field] = ['eq', $op]; + $this->options['multi'][$logic][$field][] = $where[$field]; } else { $where[$field] = [$op, $condition, isset($param[2]) ? $param[2] : null]; if ('exp' == strtolower($op) && isset($param[2]) && is_array($param[2])) { @@ -1024,18 +1178,18 @@ class Query $this->bind($param[2]); } // 记录一个字段多次查询条件 - $this->options['multi'][$field][] = $where[$field]; + $this->options['multi'][$logic][$field][] = $where[$field]; } if (!empty($where)) { if (!isset($this->options['where'][$logic])) { $this->options['where'][$logic] = []; } - if (is_string($field) && $this->checkMultiField($field)) { - $where[$field] = $this->options['multi'][$field]; + if (is_string($field) && $this->checkMultiField($field, $logic)) { + $where[$field] = $this->options['multi'][$logic][$field]; } elseif (is_array($field)) { foreach ($field as $key => $val) { - if ($this->checkMultiField($key)) { - $where[$key] = $this->options['multi'][$key]; + if ($this->checkMultiField($key, $logic)) { + $where[$key] = $this->options['multi'][$logic][$key]; } } } @@ -1043,10 +1197,16 @@ class Query } } - // 检查是否存在一个字段多次查询条件 - private function checkMultiField($field) + /** + * 检查是否存在一个字段多次查询条件 + * @access public + * @param string $field 查询字段 + * @param string $logic 查询逻辑 and or xor + * @return bool + */ + private function checkMultiField($field, $logic) { - return isset($this->options['multi'][$field]) && count($this->options['multi'][$field]) > 1; + return isset($this->options['multi'][$logic][$field]) && count($this->options['multi'][$logic][$field]) > 1; } /** @@ -1115,9 +1275,9 @@ class Query /** * 分页查询 - * @param int|null $listRows 每页数量 - * @param int|bool $simple 简洁模式或者总记录数 - * @param array $config 配置参数 + * @param int|array $listRows 每页数量 数组表示配置参数 + * @param int|bool $simple 是否简洁模式或者总记录数 + * @param array $config 配置参数 * page:当前页, * path:url路径, * query:url额外参数, @@ -1134,8 +1294,13 @@ class Query $total = $simple; $simple = false; } - $config = array_merge(Config::get('paginate'), $config); - $listRows = $listRows ?: $config['list_rows']; + if (is_array($listRows)) { + $config = array_merge(Config::get('paginate'), $listRows); + $listRows = $config['list_rows']; + } else { + $config = array_merge(Config::get('paginate'), $config); + $listRows = $listRows ?: $config['list_rows']; + } /** @var Paginator $class */ $class = false !== strpos($config['type'], '\\') ? $config['type'] : '\\think\\paginator\\driver\\' . ucwords($config['type']); @@ -1400,7 +1565,7 @@ class Query */ public function fetchPdo($pdo = true) { - $this->options['fetch_class'] = $pdo; + $this->options['fetch_pdo'] = $pdo; return $this; } @@ -1479,7 +1644,7 @@ class Query switch (strtolower($op)) { case 'today': case 'd': - $range = 'today'; + $range = ['today', 'tomorrow']; break; case 'week': case 'w': @@ -1505,6 +1670,8 @@ class Query case 'last year': $range = [mktime(0, 0, 0, 1, 1, $date['year'] - 1), mktime(0, 0, 0, 1, 1, $date['year'])]; break; + default: + $range = $op; } $op = is_array($range) ? 'between' : '>'; } @@ -2023,6 +2190,27 @@ class Query } } + /** + * 执行查询但只返回PDOStatement对象 + * @access public + * @return \PDOStatement|string + */ + public function getPdo() + { + // 分析查询表达式 + $options = $this->parseExpress(); + // 生成查询SQL + $sql = $this->builder->select($options); + // 获取参数绑定 + $bind = $this->getBind(); + if ($options['fetch_sql']) { + // 获取实际执行的SQL语句 + return $this->connection->getRealSql($sql, $bind); + } + // 执行查询操作 + return $this->query($sql, $bind, $options['master'], true); + } + /** * 查找记录 * @access public @@ -2071,7 +2259,7 @@ class Query if ($resultSet = $this->trigger('before_select', $options)) { } else { // 执行查询操作 - $resultSet = $this->query($sql, $bind, $options['master'], $options['fetch_class']); + $resultSet = $this->query($sql, $bind, $options['master'], $options['fetch_pdo']); if ($resultSet instanceof \PDOStatement) { // 返回PDOStatement对象 @@ -2174,7 +2362,7 @@ class Query if ($result = $this->trigger('before_find', $options)) { } else { // 执行查询 - $result = $this->query($sql, $bind, $options['master'], $options['fetch_class']); + $result = $this->query($sql, $bind, $options['master'], $options['fetch_pdo']); if ($result instanceof \PDOStatement) { // 返回PDOStatement对象 @@ -2454,7 +2642,7 @@ class Query $options['strict'] = $this->getConfig('fields_strict'); } - foreach (['master', 'lock', 'fetch_class', 'fetch_sql', 'distinct'] as $name) { + foreach (['master', 'lock', 'fetch_pdo', 'fetch_sql', 'distinct'] as $name) { if (!isset($options[$name])) { $options[$name] = false; } diff --git a/core/library/think/model/relation/BelongsToMany.php b/core/library/think/model/relation/BelongsToMany.php index bbab3714..428620a2 100644 --- a/core/library/think/model/relation/BelongsToMany.php +++ b/core/library/think/model/relation/BelongsToMany.php @@ -308,7 +308,7 @@ class BelongsToMany extends Relation * @param bool $relationDel 是否同时删除关联表数据 * @return integer */ - public function detach($data, $relationDel = false) + public function detach($data = null, $relationDel = false) { if (is_array($data)) { $id = $data;