diff --git a/convention.php b/convention.php index d4d94782..3b72df25 100644 --- a/convention.php +++ b/convention.php @@ -71,6 +71,8 @@ return [ 'pathinfo_depr' => '/', // 获取当前页面地址的系统变量 默认为REQUEST_URI 'url_request_uri' => 'REQUEST_URI', + // 控制器版本参数 + 'var_version' => 'version', // 基础URL路径 'base_url' => $_SERVER["SCRIPT_NAME"], // URL伪静态后缀 diff --git a/library/think/App.php b/library/think/App.php index f886ea3c..baed07cf 100644 --- a/library/think/App.php +++ b/library/think/App.php @@ -224,7 +224,7 @@ class App // 安全检测 throw new Exception('illegal controller name:' . CONTROLLER_NAME, 10000); } - $instance = Loader::controller(CONTROLLER_NAME, '', Config::get('empty_controller')); + $instance = Loader::controller(CONTROLLER_NAME, '', Config::get('empty_controller'), Input::get(Config::get('var_version'))); // 获取当前操作名 $action = ACTION_NAME . Config::get('action_suffix'); diff --git a/library/think/Loader.php b/library/think/Loader.php index beb4b4f8..24b1c185 100644 --- a/library/think/Loader.php +++ b/library/think/Loader.php @@ -322,9 +322,10 @@ class Loader * @param string $name 资源地址 * @param string $layer 控制层名称 * @param string $empty 空控制器名称 + * @param string $version 版本号 例如 1.0 1.2.3 * @return Object|false */ - public static function controller($name, $layer = '', $empty = '') + public static function controller($name, $layer = '', $empty = '', $version = null) { static $_instance = []; $layer = $layer ?: CONTROLLER_LAYER; @@ -337,6 +338,12 @@ class Loader $module = APP_MULTI_MODULE ? MODULE_NAME : ''; } $class = self::parseClass($module, $layer, $name); + if ($version) { + $filename = APP_PATH . str_replace(APP_NAMESPACE . '\\', '', dirname($class)) . DS . $version . DS . basename($class) . EXT; + if (is_file($filename)) { + require $filename; + } + } if (class_exists($class)) { $action = new $class; $_instance[$name . $layer] = $action; diff --git a/library/think/db/driver/Mongo.php b/library/think/db/driver/Mongo.php deleted file mode 100644 index 5ecf28bb..00000000 --- a/library/think/db/driver/Mongo.php +++ /dev/null @@ -1,820 +0,0 @@ - -// +---------------------------------------------------------------------- - -namespace think\db\driver; - -use think\db\Driver; -use think\Exception; -use think\Lang; - -/** - * Mongo数据库驱动 - */ -class Mongo extends Driver -{ - - protected $_mongo = null; // MongoDb Object - protected $_collection = null; // MongoCollection Object - protected $_dbName = ''; // dbName - protected $_collectionName = ''; // collectionName - protected $_cursor = null; // MongoCursor Object - protected $comparison = ['neq' => 'ne', 'ne' => 'ne', 'gt' => 'gt', 'egt' => 'gte', 'gte' => 'gte', 'lt' => 'lt', 'elt' => 'lte', 'lte' => 'lte', 'in' => 'in', 'not in' => 'nin', 'nin' => 'nin']; - - /** - * 架构函数 读取数据库配置信息 - * @access public - * - * @param array|string $config 数据库配置数组 - * - * @throws Exception - */ - public function __construct($config = '') - { - if (!class_exists('mongoClient')) { - throw new Exception(Lang::get('_NOT_SUPPERT_') . ':Mongo'); - } - if (!empty($config)) { - $this->config = array_merge($this->config, $config); - if (empty($this->config['params'])) { - $this->config['params'] = []; - } - } - } - - /** - * 连接数据库方法 - * @access public - * - * @param string $config - * @param int $linkNum - * - * @return - * @throws Exception - */ - public function connect($config = '', $linkNum = 0, $autoConnection = false) - { - if (!isset($this->links[$linkNum])) { - if (empty($config)) { - $config = $this->config; - } - - $host = 'mongodb://' . ($config['username'] ? "{$config['username']}" : '') . ($config['password'] ? ":{$config['password']}@" : '') . $config['hostname'] . ($config['hostport'] ? ":{$config['hostport']}" : '') . '/' . ($config['database'] ? "{$config['database']}" : ''); - try { - $this->links[$linkNum] = new \mongoClient($host, !empty($this->config['params']) ? $this->config['params'] : array()); - } catch (\MongoConnectionException $e) { - throw new Exception($e->getmessage()); - } - } - return $this->links[$linkNum]; - } - - /** - * 切换当前操作的Db和Collection - * @access public - * - * @param string $collection collection - * @param string $db db - * @param boolean $master 是否主服务器 - * - * @throws Exception - */ - public function switchCollection($collection, $db = '', $master = true) - { - // 当前没有连接 则首先进行数据库连接 - if (!$this->linkID) { - $this->initConnect($master); - } - - $db = $db ? $db : $this->config['database']; - - try { - if (!empty($db)) { - // 传人Db则切换数据库 - // 当前MongoDb对象 - $this->_dbName = $db; - $this->_mongo = $this->linkID->selectDb($db); - } - // 当前MongoCollection对象 - if ($this->config['debug']) { - $this->queryStr = $this->_dbName . '.getCollection(' . $collection . ')'; - } - if ($this->_collectionName != $collection) { - $this->queryTimes++; - $this->debug(true); - $this->_collection = $this->_mongo->selectCollection($collection); - $this->debug(false); - $this->_collectionName = $collection; // 记录当前Collection名称 - } - } catch (\MongoException $e) { - throw new Exception($e->getMessage()); - } - } - - /** - * 释放查询结果 - * @access public - */ - public function free() - { - $this->_cursor = null; - } - - /** - * 执行命令 - * @access public - * @param array $command 指令 - * @return array - */ - public function command($command = []) - { - $this->executeTimes++; - $this->debug(true); - $this->queryStr = 'command:' . json_encode($command); - $result = $this->_mongo->command($command); - $this->debug(false); - if (!$result['ok']) { - throw new Exception($result['errmsg']); - } - return $result; - } - - /** - * 执行语句 - * @access public - * - * @param string $code sql指令 - * @param array $args 参数 - * - * @return mixed - * @throws Exception - */ - public function execute($code, $args = []) - { - $this->executeTimes++; - $this->debug(true); - $this->queryStr = 'execute:' . $code; - $result = $this->_mongo->execute($code, $args); - $this->debug(false); - if ($result['ok']) { - return $result['retval']; - } else { - throw new Exception($result['errmsg']); - } - } - - /** - * 关闭数据库 - * @access public - */ - public function close() - { - if ($this->linkID) { - $this->linkID->close(); - $this->linkID = null; - $this->_mongo = null; - $this->_collection = null; - $this->_cursor = null; - } - } - - /** - * 数据库错误信息 - * @access public - * @return string - */ - public function getError() - { - $error = $this->_mongo->lastError(); - return $error; - } - - /** - * 插入记录 - * @access public - * - * @param mixed $data 数据 - * @param array $options 参数表达式 - * @param boolean $replace 是否replace - * - * @return false|int - * @throws Exception - */ - public function insert($data, $options = [], $replace = false) - { - if (isset($options['table'])) { - $this->switchCollection($options['table']); - } - $this->model = $options['model']; - $this->executeTimes++; - if ($this->config['debug']) { - $this->queryStr = $this->_dbName . '.' . $this->_collectionName . '.insert('; - $this->queryStr .= $data ? json_encode($data) : '{}'; - $this->queryStr .= ')'; - } - try { - $this->debug(true); - $result = $replace ? $this->_collection->save($data) : $this->_collection->insert($data); - $this->debug(false); - if ($result) { - $_id = $data['_id']; - if (is_object($_id)) { - $_id = $_id->__toString(); - } - $this->lastInsID = $_id; - } - return $result; - } catch (\MongoCursorException $e) { - throw new Exception($e->getMessage()); - } - } - - /** - * 插入多条记录 - * @access public - * - * @param array $dataList 数据 - * @param array $options 参数表达式 - * - * @return bool - * @throws Exception - */ - public function insertAll($dataList, $options = [], $replace = false) - { - if (isset($options['table'])) { - $this->switchCollection($options['table']); - } - $this->model = $options['model']; - $this->executeTimes++; - try { - $this->debug(true); - $result = $this->_collection->batchInsert($dataList); - $this->debug(false); - return $result; - } catch (\MongoCursorException $e) { - throw new Exception($e->getMessage()); - } - } - - /** - * 生成下一条记录ID 用于自增非MongoId主键 - * @access public - * - * @param string $pk 主键名 - * - * @return int - * @throws Exception - */ - public function getMongoNextId($pk) - { - if ($this->config['debug']) { - $this->queryStr = $this->_dbName . '.' . $this->_collectionName . '.find({},{' . $pk . ':1}).sort({' . $pk . ':-1}).limit(1)'; - } - try { - $this->debug(true); - $result = $this->_collection->find([], [$pk => 1])->sort([$pk => -1])->limit(1); - $this->debug(false); - } catch (\MongoCursorException $e) { - throw new Exception($e->getMessage()); - } - $data = $result->getNext(); - return isset($data[$pk]) ? $data[$pk] + 1 : 1; - } - - /** - * 更新记录 - * @access public - * - * @param mixed $data 数据 - * @param array $options 表达式 - * - * @return bool - * @throws Exception - */ - public function update($data, $options) - { - if (isset($options['table'])) { - $this->switchCollection($options['table']); - } - $this->executeTimes++; - $this->model = $options['model']; - $query = $this->parseWhere($options['where']); - $set = $this->parseSet($data); - if ($this->config['debug']) { - $this->queryStr = $this->_dbName . '.' . $this->_collectionName . '.update('; - $this->queryStr .= $query ? json_encode($query) : '{}'; - $this->queryStr .= ',' . json_encode($set) . ')'; - } - try { - $this->debug(true); - if (isset($options['limit']) && 1 == $options['limit']) { - $multiple = ["multiple" => false]; - } else { - $multiple = ["multiple" => true]; - } - $result = $this->_collection->update($query, $set, $multiple); - $this->debug(false); - return $result; - } catch (\MongoCursorException $e) { - throw new Exception($e->getMessage()); - } - } - - /** - * 删除记录 - * @access public - * @param array $options 表达式 - * @return false | integer - */ - public function delete($options = []) - { - if (isset($options['table'])) { - $this->switchCollection($options['table']); - } - $query = $this->parseWhere($options['where']); - $this->model = $options['model']; - $this->executeTimes++; - if ($this->config['debug']) { - $this->queryStr = $this->_dbName . '.' . $this->_collectionName . '.remove(' . json_encode($query) . ')'; - } - try { - $this->debug(true); - $result = $this->_collection->remove($query); - $this->debug(false); - return $result; - } catch (\MongoCursorException $e) { - throw new Exception($e->getMessage()); - } - } - - /** - * 清空记录 - * @access public - * @param array $options 表达式 - * @return false | integer - */ - public function clear($options = []) - { - if (isset($options['table'])) { - $this->switchCollection($options['table']); - } - $this->model = $options['model']; - $this->executeTimes++; - if ($this->config['debug']) { - $this->queryStr = $this->_dbName . '.' . $this->_collectionName . '.remove({})'; - } - try { - $this->debug(true); - $result = $this->_collection->drop(); - $this->debug(false); - return $result; - } catch (\MongoCursorException $e) { - throw new Exception($e->getMessage()); - } - } - - /** - * 查找记录 - * @access public - * @param array $options 表达式 - * @return iterator - */ - public function select($options = []) - { - if (isset($options['table'])) { - $this->switchCollection($options['table'], '', false); - } - $cache = isset($options['cache']) ? $options['cache'] : false; - if ($cache) { - // 查询缓存检测 - $key = is_string($cache['key']) ? $cache['key'] : md5(serialize($options)); - $value = S($key, '', '', $cache['type']); - if (false !== $value) { - return $value; - } - } - $this->model = $options['model']; - $this->queryTimes++; - $query = $this->parseWhere(!empty($options['where']) ? $options['where'] : array()); - $field = $this->parseField(!empty($options['field']) ? $options['field'] : ''); - try { - if ($this->config['debug']) { - $this->queryStr = $this->_dbName . '.' . $this->_collectionName . '.find('; - $this->queryStr .= $query ? json_encode($query) : '{}'; - $this->queryStr .= $field ? ',' . json_encode($field) : ''; - $this->queryStr .= ')'; - } - $this->debug(true); - $_cursor = $this->_collection->find($query, $field); - if ($options['order']) { - $order = $this->parseOrder($options['order']); - if ($this->config['debug']) { - $this->queryStr .= '.sort(' . json_encode($order) . ')'; - } - $_cursor = $_cursor->sort($order); - } - if (isset($options['page'])) { - // 根据页数计算limit - if (strpos($options['page'], ',')) { - list($page, $length) = explode(',', $options['page']); - } else { - $page = $options['page']; - } - $page = $page ? $page : 1; - $length = isset($length) ? $length : (is_numeric($options['limit']) ? $options['limit'] : 20); - $offset = $length * ((int) $page - 1); - $options['limit'] = $offset . ',' . $length; - } - if (isset($options['limit'])) { - list($offset, $length) = $this->parseLimit($options['limit']); - if (!empty($offset)) { - if ($this->config['debug']) { - $this->queryStr .= '.skip(' . intval($offset) . ')'; - } - $_cursor = $_cursor->skip(intval($offset)); - } - if ($this->config['debug']) { - $this->queryStr .= '.limit(' . intval($length) . ')'; - } - $_cursor = $_cursor->limit(intval($length)); - } - $this->debug(false); - $this->_cursor = $_cursor; - $resultSet = iterator_to_array($_cursor); - if ($cache && $resultSet) { - // 查询缓存写入 - S($key, $resultSet, $cache['expire'], $cache['type']); - } - return $resultSet; - } catch (\MongoCursorException $e) { - throw new Exception($e->getMessage()); - } - } - - /** - * 查找某个记录 - * @access public - * @param array $options 表达式 - * @return array - */ - public function find($options = []) - { - if (isset($options['table'])) { - $this->switchCollection($options['table'], '', false); - } - $cache = isset($options['cache']) ? $options['cache'] : false; - if ($cache) { - // 查询缓存检测 - $key = is_string($cache['key']) ? $cache['key'] : md5(serialize($options)); - $value = S($key, '', '', $cache['type']); - if (false !== $value) { - return $value; - } - } - $this->model = $options['model']; - $this->queryTimes++; - $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) : '{}'; - $this->queryStr .= $fields ? ',' . json_encode($fields) : ''; - $this->queryStr .= ')'; - } - try { - $this->debug(true); - $result = $this->_collection->findOne($query, $fields); - $this->debug(false); - if ($cache && $result) { - // 查询缓存写入 - S($key, $result, $cache['expire'], $cache['type']); - } - return $result; - } catch (\MongoCursorException $e) { - throw new Exception($e->getMessage()); - } - } - - /** - * 统计记录数 - * @access public - * @param array $options 表达式 - * @return iterator - */ - public function count($options = []) - { - if (isset($options['table'])) { - $this->switchCollection($options['table'], '', false); - } - $this->model = $options['model']; - $this->queryTimes++; - $query = $this->parseWhere($options['where']); - if ($this->config['debug']) { - $this->queryStr = $this->_dbName . '.' . $this->_collectionName; - $this->queryStr .= $query ? '.find(' . json_encode($query) . ')' : ''; - $this->queryStr .= '.count()'; - } - try { - $this->debug(true); - $count = $this->_collection->count($query); - $this->debug(false); - return $count; - } catch (\MongoCursorException $e) { - throw new Exception($e->getMessage()); - } - } - - public function group($keys, $initial, $reduce, $options = []) - { - $this->_collection->group($keys, $initial, $reduce, $options); - } - - /** - * 取得数据表的字段信息 - * @access public - * @return array - */ - public function getFields($collection = '') - { - if (!empty($collection) && $collection != $this->_collectionName) { - $this->switchCollection($collection, '', false); - } - $this->queryTimes++; - if ($this->config['debug']) { - $this->queryStr = $this->_dbName . '.' . $this->_collectionName . '.findOne()'; - } - try { - $this->debug(true); - $result = $this->_collection->findOne(); - $this->debug(false); - } catch (\MongoCursorException $e) { - throw new Exception($e->getMessage()); - } - if ($result) { - // 存在数据则分析字段 - $info = []; - foreach ($result as $key => $val) { - $info[$key] = [ - 'name' => $key, - 'type' => getType($val), - ]; - } - return $info; - } - // 暂时没有数据 返回false - return false; - } - - /** - * 取得当前数据库的collection信息 - * @access public - */ - public function getTables() - { - if ($this->config['debug']) { - $this->queryStr = $this->_dbName . '.getCollenctionNames()'; - } - $this->queryTimes++; - $this->debug(true); - $list = $this->_mongo->listCollections(); - $this->debug(false); - $info = []; - foreach ($list as $collection) { - $info[] = $collection->getName(); - } - return $info; - } - - /** - * set分析 - * @access protected - * @param array $data - * @return string - */ - protected function parseSet($data) - { - $result = []; - foreach ($data as $key => $val) { - if (is_array($val)) { - switch ($val[0]) { - case 'inc': - $result['$inc'][$key] = (int) $val[1]; - break; - case 'set': - case 'unset': - case 'push': - case 'pushall': - case 'addtoset': - case 'pop': - case 'pull': - case 'pullall': - $result['$' . $val[0]][$key] = $val[1]; - break; - default: - $result['$set'][$key] = $val; - } - } else { - $result['$set'][$key] = $val; - } - } - return $result; - } - - /** - * order分析 - * @access protected - * @param mixed $order - * @return array - */ - protected function parseOrder($order) - { - if (is_array($order)) { - $order = join(',', $order); - } - if (is_string($order)) { - $array = explode(',', $order); - $order = []; - foreach ($array as $key => $val) { - $arr = explode(' ', trim($val)); - if (isset($arr[1])) { - $arr[1] = 'asc' == $arr[1] ? 1 : -1; - } else { - $arr[1] = 1; - } - $order[$arr[0]] = $arr[1]; - } - } - return $order; - } - - /** - * limit分析 - * @access protected - * @param mixed $limit - * @return array - */ - protected function parseLimit($limit) - { - if (strpos($limit, ',')) { - $array = explode(',', $limit); - } else { - $array = [0, $limit]; - } - return $array; - } - - /** - * field分析 - * @access protected - * @param mixed $fields - * @return array - */ - public function parseField($fields) - { - if (empty($fields)) { - $fields = []; - } - if (is_string($fields)) { - $fields = explode(',', $fields); - } - return $fields; - } - - /** - * where分析 - * @access protected - * @param mixed $where - * @return array - */ - public function parseWhere($where) - { - $query = []; - foreach ((array) $where as $key => $val) { - if ('_id' != $key && 0 === strpos($key, '_')) { - // 解析特殊条件表达式 - $query = $this->parseThinkWhere($key, $val); - } else { - // 查询字段的安全过滤 - if (!preg_match('/^[A-Z_\|\&\-.a-z0-9]+$/', trim($key))) { - throw new Exception(Lang::get('_ERROR_QUERY_') . ':' . $key); - } - $key = trim($key); - if (strpos($key, '|')) { - $array = explode('|', $key); - $str = []; - foreach ($array as $k) { - $str[] = $this->parseWhereItem($k, $val); - } - $query['$or'] = $str; - } elseif (strpos($key, '&')) { - $array = explode('&', $key); - $str = []; - foreach ($array as $k) { - $str[] = $this->parseWhereItem($k, $val); - } - $query = array_merge($query, $str); - } else { - $str = $this->parseWhereItem($key, $val); - $query = array_merge($query, $str); - } - } - } - return $query; - } - - /** - * 特殊条件分析 - * @access protected - * @param string $key - * @param mixed $val - * @return string - */ - protected function parseThinkWhere($key, $val) - { - $query = []; - switch ($key) { - case '_query': // 字符串模式查询条件 - parse_str($val, $query); - if (isset($query['_logic']) && strtolower($query['_logic']) == 'or') { - unset($query['_logic']); - $query['$or'] = $query; - } - break; - case '_string': // MongoCode查询 - $query['$where'] = new \MongoCode($val); - break; - } - return $query; - } - - /** - * where子单元分析 - * @access protected - * @param string $key - * @param mixed $val - * @return array - */ - protected function parseWhereItem($key, $val) - { - $query = []; - if (is_array($val)) { - if (is_string($val[0])) { - $con = strtolower($val[0]); - if (in_array($con, ['neq', 'ne', 'gt', 'egt', 'gte', 'lt', 'lte', 'elt'])) { - // 比较运算 - $k = '$' . $this->comparison[$con]; - $query[$key] = [$k => $val[1]]; - } elseif ('like' == $con) { - // 模糊查询 采用正则方式 - $query[$key] = new \MongoRegex("/" . $val[1] . "/"); - } elseif ('mod' == $con) { - // mod 查询 - $query[$key] = ['$mod' => $val[1]]; - } elseif ('regex' == $con) { - // 正则查询 - $query[$key] = new \MongoRegex($val[1]); - } elseif (in_array($con, ['in', 'nin', 'not in'])) { - // IN NIN 运算 - $data = is_string($val[1]) ? explode(',', $val[1]) : $val[1]; - $k = '$' . $this->comparison[$con]; - $query[$key] = [$k => $data]; - } elseif ('all' == $con) { - // 满足所有指定条件 - $data = is_string($val[1]) ? explode(',', $val[1]) : $val[1]; - $query[$key] = ['$all' => $data]; - } elseif ('between' == $con) { - // BETWEEN运算 - $data = is_string($val[1]) ? explode(',', $val[1]) : $val[1]; - $query[$key] = ['$gte' => $data[0], '$lte' => $data[1]]; - } elseif ('not between' == $con) { - $data = is_string($val[1]) ? explode(',', $val[1]) : $val[1]; - $query[$key] = ['$lt' => $data[0], '$gt' => $data[1]]; - } elseif ('exp' == $con) { - // 表达式查询 - $query['$where'] = new \MongoCode($val[1]); - } elseif ('exists' == $con) { - // 字段是否存在 - $query[$key] = ['$exists' => (bool) $val[1]]; - } elseif ('size' == $con) { - // 限制属性大小 - $query[$key] = ['$size' => intval($val[1])]; - } elseif ('type' == $con) { - // 限制字段类型 1 浮点型 2 字符型 3 对象或者MongoDBRef 5 MongoBinData 7 MongoId 8 布尔型 9 MongoDate 10 NULL 15 MongoCode 16 32位整型 17 MongoTimestamp 18 MongoInt64 如果是数组的话判断元素的类型 - $query[$key] = ['$type' => intval($val[1])]; - } else { - $query[$key] = $val; - } - return $query; - } - } - $query[$key] = $val; - return $query; - } -} diff --git a/library/think/model/Mongo.php b/library/think/model/Mongo.php deleted file mode 100644 index 00d72624..00000000 --- a/library/think/model/Mongo.php +++ /dev/null @@ -1,311 +0,0 @@ - -// +---------------------------------------------------------------------- -namespace think\model; - -use think\Lang; -use think\Loader; - -\think\Loader::import('modle/Adv', TRAIT_PATH, EXT); - -/** - * MongoModel模型类 - * 实现了ODM和ActiveRecords模式 - */ -class Mongo extends \think\Model -{ - use \traits\model\Adv; - - // 主键类型 - const TYPE_OBJECT = 1; - const TYPE_INT = 2; - const TYPE_STRING = 3; - - // 主键名称 - protected $pk = '_id'; - // _id 类型 1 Object 采用MongoId对象 2 Int 整形 支持自动增长 3 String 字符串Hash - protected $_idType = self::TYPE_OBJECT; - // 主键是否自动增长 支持Int型主键 - protected $_autoInc = false; - // Mongo默认关闭字段检测 可以动态追加字段 - protected $autoCheckFields = false; - - /** - * 利用__call方法实现一些特殊的Model方法 - * @access public - * - * @param string $method 方法名称 - * @param array $args 调用参数 - * - * @return mixed - * @throws \think\Exception - */ - public function __call($method, $args) - { - if (strtolower(substr($method, 0, 5)) == 'getby') { - // 根据某个字段获取记录 - $field = Loader::parseName(substr($method, 5)); - $where[$field] = $args[0]; - return $this->where($where)->find(); - } elseif (strtolower(substr($method, 0, 10)) == 'getfieldby') { - // 根据某个字段获取记录的某个值 - $name = Loader::parseName(substr($method, 10)); - $where[$name] = $args[0]; - return $this->where($where)->getField($args[1]); - } else { - throw new \think\Exception(__CLASS__ . ':' . $method . Lang::get('_METHOD_NOT_EXIST_')); - } - } - - // 写入数据前的回调方法 包括新增和更新 - protected function _before_write(&$data) - { - $pk = $this->getPk(); - // 根据主键类型处理主键数据 - if (isset($data[$pk]) && self::TYPE_OBJECT == $this->_idType) { - $data[$pk] = new MongoId($data[$pk]); - } - } - - /** - * count统计 配合where连贯操作 - * @access public - * @return integer - */ - public function count() - { - // 分析表达式 - $options = $this->_parseOptions(); - return $this->db->count($options); - } - - /** - * 获取下一ID 用于自动增长型 - * @access public - * @param string $pk 字段名 默认为主键 - * @return mixed - */ - public function getMongoNextId($pk = '') - { - if (empty($pk)) { - $pk = $this->getPk(); - } - return $this->db->getMongoNextId($pk); - } - - // 插入数据前的回调方法 - protected function _before_insert(&$data, $options = []) - { - // 写入数据到数据库 - if ($this->_autoInc && self::TYPE_INT == $this->_idType) { - // 主键自动增长 - $pk = $this->getPk(); - if (!isset($data[$pk])) { - $data[$pk] = $this->db->mongo_next_id($pk); - } - } - } - - public function clear() - { - return $this->db->clear(); - } - - // 查询成功后的回调方法 - protected function _after_select(&$resultSet, $options = []) - { - array_walk($resultSet, [$this, 'checkMongoId']); - } - - /** - * 获取MongoId - * @access protected - * @param array $result 返回数据 - * @return array - */ - protected function checkMongoId(&$result) - { - if (is_object($result['_id'])) { - $result['_id'] = $result['_id']->__toString(); - } - return $result; - } - - // 表达式过滤回调方法 - protected function _options_filter(&$options) - { - $id = $this->getPk(); - if (isset($options['where'][$id]) && is_scalar($options['where'][$id]) && self::TYPE_OBJECT == $this->_idType) { - $options['where'][$id] = new MongoId($options['where'][$id]); - } - } - - /** - * 查询数据 - * @access public - * @param mixed $options 表达式参数 - * @return mixed - */ - public function find($options = []) - { - if (is_numeric($options) || is_string($options)) { - $id = $this->getPk(); - $where[$id] = $options; - $options = []; - $options['where'] = $where; - } - // 分析表达式 - $options = $this->_parseOptions($options); - $result = $this->db->find($options); - if (false === $result) { - return false; - } - if (empty($result)) { - // 查询结果为空 - return null; - } else { - $this->checkMongoId($result); - } - $this->data = $result; - $this->_after_find($this->data, $options); - return $this->data; - } - - /** - * 字段值增长 - * @access public - * @param string $field 字段名 - * @param integer $step 增长值 - * @return boolean - */ - public function setInc($field, $step = 1, $lazyTime = 0) - { - return $this->setField($field, ['inc', $step]); - } - - /** - * 字段值减少 - * @access public - * @param string $field 字段名 - * @param integer $step 减少值 - * @return boolean - */ - public function setDec($field, $step = 1, $lazyTime = 0) - { - return $this->setField($field, ['inc', '-' . $step]); - } - - /** - * 获取一条记录的某个字段值 - * @access public - * @param string $field 字段名 - * @param string $spea 字段数据间隔符号 - * @return mixed - */ - public function getField($field, $sepa = null) - { - $options['field'] = $field; - $options = $this->_parseOptions($options); - if (strpos($field, ',')) { - // 多字段 - if (is_numeric($sepa)) { - // 限定数量 - $options['limit'] = $sepa; - $sepa = null; // 重置为null 返回数组 - } - $resultSet = $this->db->select($options); - if (!empty($resultSet)) { - $_field = explode(',', $field); - $field = array_keys($resultSet[0]); - $key = array_shift($field); - $key2 = array_shift($field); - $cols = []; - $count = count($_field); - foreach ($resultSet as $result) { - $name = $result[$key]; - if (2 == $count) { - $cols[$name] = $result[$key2]; - } else { - $cols[$name] = is_null($sepa) ? $result : implode($sepa, $result); - } - } - return $cols; - } - } else { - // 返回数据个数 - if (true !== $sepa) { - // 当sepa指定为true的时候 返回所有数据 - $options['limit'] = is_numeric($sepa) ? $sepa : 1; - } - // 查找一条记录 - $result = $this->db->find($options); - if (!empty($result)) { - if (1 == $options['limit']) { - return reset($result[0]); - } - - foreach ($result as $val) { - $array[] = $val[$field]; - } - return $array; - } - } - return null; - } - - /** - * 执行Mongo指令 - * @access public - * @param array $command 指令 - * @return mixed - */ - public function command($command) - { - return $this->db->command($command); - } - - /** - * 执行MongoCode - * @access public - * @param string $code MongoCode - * @param array $args 参数 - * @return mixed - */ - public function mongoCode($code, $args = []) - { - return $this->db->execute($code, $args); - } - - // 数据库切换后回调方法 - protected function _after_db() - { - // 切换Collection - $this->db->switchCollection($this->getTableName(), $this->dbName); - } - - /** - * 得到完整的数据表名 Mongo表名不带dbName - * @access public - * @return string - */ - public function getTableName() - { - if (empty($this->trueTableName)) { - $tableName = !empty($this->tablePrefix) ? $this->tablePrefix : ''; - if (!empty($this->tableName)) { - $tableName .= $this->tableName; - } else { - $tableName .= Loader::parseName($this->name); - } - $this->trueTableName = strtolower($tableName); - } - return $this->trueTableName; - } -}