Sin Descripción

MongoModel.class.php 14KB

    <?php // +---------------------------------------------------------------------- // | TOPThink [ WE CAN DO IT JUST THINK ] // +---------------------------------------------------------------------- // | Copyright (c) 2010 http://topthink.com All rights reserved. // +---------------------------------------------------------------------- // | Licensed ( http://www.apache.org/licenses/LICENSE-2.0 ) // +---------------------------------------------------------------------- // | Author: liu21st <liu21st@gmail.com> // +---------------------------------------------------------------------- // $Id: MongoModel.class.php 2576 2012-01-12 15:09:01Z liu21st $ /** +------------------------------------------------------------------------------ * TOPThink MongoModel模型类 * 实现了ODM和ActiveRecords模式 +------------------------------------------------------------------------------ * @category Think * @package Think * @subpackage Core * @author liu21st <liu21st@gmail.com> * @version $Id: MongoModel.class.php 2576 2012-01-12 15:09:01Z liu21st $ +------------------------------------------------------------------------------ */ class MongoModel extends Model{ // 主键类型 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 +---------------------------------------------------------- */ public function __call($method,$args) { if(in_array(strtolower($method),array('table','where','order','limit','page'),true)) { // 连贯操作的实现 $this->options[strtolower($method)] = $args[0]; return $this; }elseif(strtolower(substr($method,0,5))=='getby') { // 根据某个字段获取记录 $field = parse_name(substr($method,5)); $where[$field] =$args[0]; return $this->where($where)->find(); }elseif(strtolower(substr($method,0,10))=='getfieldby') { // 根据某个字段获取记录的某个值 $name = parse_name(substr($method,10)); $where[$name] =$args[0]; return $this->where($where)->getField($args[1]); }else{ throw_exception(__CLASS__.':'.$method.L('_METHOD_NOT_EXIST_')); return; } } /** +---------------------------------------------------------- * 获取字段信息并缓存 主键和自增信息直接配置 +---------------------------------------------------------- * @access public +---------------------------------------------------------- * @return void +---------------------------------------------------------- */ public function flush() { // 缓存不存在则查询数据表信息 $fields = $this->db->getFields(); if(!$fields) { // 暂时没有数据无法获取字段信息 下次查询 return false; } $this->fields = array_keys($fields); $this->fields['_pk'] = $this->pk; $this->fields['_autoinc'] = $this->_autoInc; foreach ($fields as $key=>$val){ // 记录字段类型 $type[$key] = $val['type']; } // 记录字段类型信息 if(C('DB_FIELDTYPE_CHECK')) $this->fields['_type'] = $type; // 2008-3-7 增加缓存开关控制 if(C('DB_FIELDS_CACHE')){ // 永久缓存数据表信息 $db = $this->dbName?$this->dbName:C('DB_NAME'); F('_fields/'.$db.'.'.$this->name,$this->fields); } } // 写入数据前的回调方法 包括新增和更新 protected function _before_write(&$data) { $pk = $this->getPk(); // 根据主键类型处理主键数据 if(isset($data[$pk]) && $this->_idType == self::TYPE_OBJECT) { $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->mongo_next_id($pk); } // 插入数据前的回调方法 protected function _before_insert(&$data,$options) { // 写入数据到数据库 if($this->_autoInc && $this->_idType== self::TYPE_INT) { // 主键自动增长 $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,array($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]) && $this->_idType== self::TYPE_OBJECT) { $options['where'][$id] = new MongoId($options['where'][$id]); } } /** +---------------------------------------------------------- * 查询数据 +---------------------------------------------------------- * @access public +---------------------------------------------------------- * @param mixed $options 表达式参数 +---------------------------------------------------------- * @return mixed +---------------------------------------------------------- */ public function find($options=array()) { if( is_numeric($options) || is_string($options)) { $id = $this->getPk(); $where[$id] = $options; $options = array(); $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) { return $this->setField($field,array('inc',$step)); } /** +---------------------------------------------------------- * 字段值减少 +---------------------------------------------------------- * @access public +---------------------------------------------------------- * @param string $field 字段名 * @param integer $step 减少值 +---------------------------------------------------------- * @return boolean +---------------------------------------------------------- */ public function setDec($field,$step=1) { return $this->setField($field,array('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,',')) { // 多字段 $resultSet = $this->db->select($options); if(!empty($resultSet)) { $_field = explode(',', $field); $field = array_keys($resultSet[0]); $move = $_field[0]==$_field[1]?false:true; $key = array_shift($field); $key2 = array_shift($field); $cols = array(); $count = count($_field); foreach ($resultSet as $result){ $name = $result[$key]; if($move) { // 删除键值记录 unset($result[$key]); } if(2==$count) { $cols[$name] = $result[$key2]; }else{ $cols[$name] = is_null($sepa)?$result:implode($sepa,$result); } } return $cols; } }else{ // 查找一条记录 $result = $this->db->find($options); if(!empty($result)) { return $result[$field]; } } 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=array()) { return $this->db->execute($code,$args); } // 数据库切换后回调方法 protected function _after_db() { // 切换Collection $this->db->switchCollection($this->getTableName(),$this->dbName?$this->dbName:C('db_name')); } /** +---------------------------------------------------------- * 得到完整的数据表名 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 .= parse_name($this->name); } $this->trueTableName = strtolower($tableName); } return $this->trueTableName; } }