1. 程式人生 > >Mongodb PHP封裝類

Mongodb PHP封裝類


分享一個Mongodb PHP封裝類


<?php
/**
* Mongodb 基本操作API,支援基本類似關係統型資料庫的操作介面
*
* @version 1.0
 * [說明]
 *
 * 1:該版本API實現了 Mongodb 中最基本的插入/修改/查詢/刪除操作的封裝
 * 2:其它更高階的操作可通過 $this->getMongo() 得到原生的物件,更多API請自行查閱 Mongo PHP手冊,後續版本將會對增加更多的原生API封裝
 * 3:該類所有API介面中的 $query 查詢引數的使用請以下有關 [查詢條件說明文件]
 * 4: 如果要儲存中文字元,則一定要使用 utf8 的編碼.
 * 5:有了本類介面基本可以按關係型資料庫的概念完成Mongodb的大部分開發操作。
 *
 * [查詢條件說明文件]
 *
 * 引數:array('id'=>1)
 * 等同:where id=1
 *
 * 引數:array('id'=>1,'num'=>10)
 * 等同:where id=1 and num=10
 *
 * 引數:array('id'=>array($mongo->cmd('>')=>5))
 * 等同:where id>5
 *
 * 引數:array('id'=>array($mongo->cmd('!=')=>5))
 * 等同:where id!=5
 *
 * 引數:array('id'=>array($mongo->cmd('>')=>5, $mongo->cmd('<')=>10))
 * 等同:where id>5 and id<10
 *
 * 引數:array('id'=>array($mongo->cmd('in')=>array(2,5,6)))
 * 等同:where id in (2,5,6)
 *
 * 引數:array('id'=>array($mongo->cmd('%')=>array(2,1)))
 * 等同:where id % 2 = 1
 *
 * 引數:array($mongo->cmd('or') => array( array('id'=>array($mongo->cmd('>')=>5)), array('id'=>array($mongo->cmd('<')=>10)) ) )
 * 等同:where id>5 or id<10
 *
 * 引數:array('username' => new mongoRegex("/yhp.*/")) 
 * 等同 where  username  like "%yhp%"
 **/
class Library_Mongodb {

    /**
     * Mongodb 物件控制代碼
     *
     * @var object Mongo
     */
    private $_mongo = null;

    /**
     * 當前選擇的資料庫
     *
     * @var object MongoDB
     */
    private $_db = null;

    /**
     * 修改器命令字首
     *
     * @var string
     */
    private $_cmd = '$';    /**
     * 除錯模式 TRUE 開啟 FALSE 關閉
     * @var boolean
     */
    const DEBUG = TRUE;

    /**
     * 查詢條件對映關係
     *
     * @var array
     */
    private $_condMap = array(
        '<'        =>    'lt', // id > 1
        '<='    =>    'lte', // id <= 10
        '>'        =>    'gt', // id > 5
        '>='    =>    'gte', // id >= 4
        '!='    =>    'ne', // id != 4
        '%'        =>    'mod', // id % 4 = 0
        'in'    =>    'in', // id in (1,2,3,4)
        'notin'    =>    'nin',// id not in (1,2,3,4)
        'or'    =>    'or', // id=1 or id=2
        'not'    =>    'not', // !(id=1)
    );    /**
     * 建構函式
     *
     * @param array $config 伺服器配置,預設為:
     * array(
     * 'host'=>'localhost', // 主機名或IP地址
     * 'port'=>27017, // 埠
     * 'cmd'=>'$', // 修改器命令字首
     * )
     */
    public function __construct($config = array('host' => 'xxx', 'port' => 27017, 'username' => 'xxx', 'password' => 'xxx', 'db' => 'xxx',  'cmd' => '$')){
        $server = sprintf("mongodb://%s:%
[email protected]
%s:%s/%s", $config['username'], $config['password'], $config['host'], $config['port'], $config['db']); // echo "connect\n"; try { $this->_mongo = new MongoClient($server, array('connect'=>true));// 立即連線 }catch (MongoConnectionException $e){ if(self::DEBUG) { echo $e->getMessage(); } return false; } $this->selectDB($config['db']); // 命令字首 if(!isset($config['cmd'])){ $this->_cmd = ini_get('mongo.cmd'); if($this->_cmd == ''){ $this->_cmd = '$'; } } } /* ==================================== 基本操作介面API ================================= */ /** * 向集合(表)中插入新文件 * * 說明: * 1:類似mysql中的: insert into $colName set id=1,name='name1'; * * @param string $colName 集合名 * @param array $sets 資料,如: array('id'=>1,'name'=>'name1') * @param boolean $safe 是否安全操作 false:不等待伺服器的響應直接返回 true:等待伺服器的響應(資料非常重要時推薦) * @param boolean $fsync 操作後是否立即更新到碰盤,預設情況下由伺服器決定 * * @return boolean */ public function insert($colName, $sets, $safe=false, $fsync=false){ $col = $this->_getCol($colName); try { $col->insert($sets,array('w'=>$safe,'fsync'=>$fsync)); return true; }catch (MongoCursorException $e){ return false; } } /** * 儲存文件 * * 說明: * 1:如果 $sets 中有欄位 "_id" 的話,則更新對應的文件;否則插入新文件 * * @param string $colName 集合名 * @param array $sets 資料,如: array('id'=>1,'name'=>'name1') * @param boolean $safe 是否安全操作 false:不等待伺服器的響應直接返回 true:等待伺服器的響應(資料非常重要時推薦) * @param boolean $fsync 操作後是否立即更新到碰盤,預設情況下由伺服器決定 * * @return boolean */ public function save($colName, $sets, $safe=false, $fsync=false){ // 處理 '_id' 欄位 $sets = $this->_parseId($sets); $ret = $this->_getCol($colName)->save($sets,array('w'=>$safe,'fsync'=>$fsync)); return $ret; } /** * 刪除集合中的文件記錄 * * 說明: * 1:類似mysql中的: delete from $colName where id=1; * * @param string $colName 集合名 * @param array $query 查詢條件,如果為空陣列的話,則會刪除所有記錄.具體請看 [查詢條件說明文件] * @param boolean $delAll 是否刪除所以條例查詢的記錄,預設為 true,當為 false是,類似效果 delete from tab where id=1 limit 1; * @param boolean $safe 是否安全操作 false:不等待伺服器的響應直接返回 true:等待伺服器的響應(資料非常重要時推薦) * @param boolean $fsync 操作後是否立即更新到碰盤,預設情況下由伺服器決定 * * @return boolean */ public function delete($colName,$query=array(),$delAll=true,$safe=false,$fsync=false){ // 自動處理 '_id' 欄位 $query = $this->_parseId($query); // 刪除選項 $options = array( 'justOne' => !$delAll, 'w' => $safe, 'fsync' => $fsync, ); $col = $this->_getCol($colName); return $col->remove($query,$options); } /** * 刪除整個集合 * * 說明: * 1:集合中的索引也會被刪除 * * @param string $colName 集合名 * * @return array */ public function dropCol($colName){ return $this->_getCol($colName)->drop(); } /** * 更新集合文件記錄 * * 說明: * 1:類似mysql中的: update $colName set name='mongo' where id=10; * * @param string $colName 集合名 * @param array $newDoc 要更新的文件記錄 * @param array $query 查詢條件,如果為空陣列則更新所有記錄.具體請看 [查詢條件說明文件] * @param string $option 操作選項,可選擇項如下; * * 'set':只修改指定的欄位(預設值,如果這個鍵不存在,則建立它。存在則更新). * 示例: update('user', array('name'=>'mongo'), array('id'=>10)); * 類似: update user set name='mongo' where id=10; * * 'inc':將指定的欄位累加/減(如果值為負數則是相減,不存在鍵則建立。欄位型別一定要是數字) * 示例:update('user', array('num'=>1), array('id'=>10), 'inc'); * 類似: update user set num=num+1 where id=10; * * 'push':將文件新增到指定鍵中(陣列),如果鍵不存在則會自動建立,存在則新增到該鍵的尾端。 * 示例:update('user', array('comm'=>array('commid'=>1,'title'=>'title1')), array('id'=>1), 'push'); * 解說:為 id=1 的記錄新增一個 comm 的評論欄位,該欄位對應一個 array('commid'=>1,'title'=>'title1') 的新文件。 * * 'pop':將指定鍵中的文件刪除(陣列) * 示例:update('user', array('comm'=>array('commid'=>1)), array('id'=>1), 'pop'); * 解說:刪除 id=1 的記錄中 comm 對應的文件集合中 'commid'=>1 對應的文件. * * 'unset':在文件中刪除指定的鍵 * 示例:update('user', array('name'=>1), array('id'=>1), 'unset'); * 解說: 將 user 集合中將 id=1 對應的文件中的 name 欄位刪除 * * 'pull':刪除文件中匹配其值的鍵 * 示例:update('user', array('name'=>'youname'), array('id'=>1), 'pull'); * 解說:將 user 集合中將 id=1 對應的文件中的 name='youname' 的欄位刪除 * * 'addToSet':如果值不存在就新增(避免重複新增) * 示例:update('user', array('names'=>'youname'), array('id'=>1), 'addToSet'); * 解說:向 user 集合中 id=1 對應的文件中的 names 欄位新增 'youname' 這個值(不存在時才新增) * * 'replace':用 $newDoc 新文件替換 $query 所找到的文件 * 示例:update('user', array('newid'=>1,'newnames'=>'name1'), array('id'=>1), 'replace'); * 解說:將 user 集合中 id=1 對應的文件用 array('newid'=>1,'newnames'=>'name1') 的新文件替換 * * @param boolean $upAll 是否更新找到的所有記錄 * @param boolean $upsert 如果查詢條件不存在時,是否以查詢條件和要更新的欄位一起新建一個集合 * @param boolean $safe 是否安全刪除 false:不等待伺服器的響應直接返回 true:等待伺服器的響應(資料非常重要時推薦) * @param boolean $fsync 操作後是否立即更新到碰盤,預設情況下由伺服器決定 * * @return boolean */ public function update($colName,$newDoc,$query=array(),$option='set',$upAll=true,$upsert=false,$safe=false,$fsync=false){ // 自動處理 '_id' 欄位 $query = $this->_parseId($query); // 得到集合 $col = $this->_getCol($colName); // 重新組合新文件 if($option != 'replace'){ $newDoc = array($this->cmd($option) => $newDoc); } // 更新條件 $options = array( 'upsert' => $upsert, 'multiple' => $upAll, 'w' => $safe, 'fsync' => $fsync, ); return $col->update($query,$newDoc,$options); } /** * 查詢文件集,返回二維陣列 * * 說明: * 1:類似mysql中的 select * from table * * 示例:select('user'); * 類似:select * from user; * * 示例:select('user',array('id','name')); * 類似:select id,name from user; * * 示例:select('user',array('id','name'),array('id'=>1)); * 類似:select id,name from user where id=1; * * 示例:select('user',array('id','name'),array('id'=>1),array('num'=>1)); * 類似:select id,name from user where id=1 order by num asc; * * 示例:select('user',array('id','name'),array('id'=>1),array('num'=>1),10); * 類似:select id,name from user where id=1 order by num asc limit 10; * * 示例:select('user',array('id','name'),array('id'=>1),array('num'=>1),10,2); * 類似:select id,name from user where id=1 order by num asc limit 2,10; * * * * @param string $colName 集合名 * @param array $query 查詢條件,具體請看 [查詢條件說明文件] * @param array $fields 結果集返回的欄位, array():表示返回所有欄位 array('id','name'):表示只返回欄位 "id,name" * @param array $sort 排序欄位, array('id'=>1):表示按id欄位升序 array('id'=>-1):表示按id欄位降序 array('id'=>1, 'age'=>-1):表示按id升序後再按age降序 * @param int $limit 取多少條記錄 * @param int $skip 跳過多少條(從多少條開始) * * @return array */ public function select($colName,$query=array(),$fields=array(),$sort=array(),$limit=0,$skip=0){ // 得到集合 $col = $this->_getCol($colName); // 自動處理 '_id' 欄位 $query = $this->_parseId($query); // 結果集偏歷 $cursor = $col->find($query,$fields); // 排序 if($sort){ $cursor->sort($sort); } // 跳過記錄數 if($skip > 0){ $cursor->skip($skip); } // 取多少行記錄 if($limit > 0){ $cursor->limit($limit); } $result = array(); foreach($cursor as $row){ $result[] = $this->_parseArr($row); } return $result; } /** * 統計文件記錄數 * * @param string $colName 集合名 * @param array $query 查詢條件,具體請看 [查詢條件說明文件] * @param int $limit 取多少條記錄 * @param int $skip 跳過多少條 * @return unknown */ public function count($colName,$query=array(),$limit=0,$skip=0){ return $this->_getCol($colName)->count($query,$limit,$skip); } /** * 返回集合中的一條記錄(一維陣列) * * @param string $colName 集合名 * @param array $query 查詢條件,具體請看 [查詢條件說明文件] * @param array $fields 結果集返回的欄位, array():表示返回所有欄位 array('id','name'):表示只返回欄位 "id,name" * * @return array */ public function fetchRow($colName,$query=array(), $fields=array()){ // 得到集合名 $col = $this->_getCol($colName); // 自動處理 '_id' 欄位 $query = $this->_parseId($query); // 處理結果集 return $this->_parseArr($col->findOne($query,$fields)); } /** * 返回符合條件的文件中欄位的值 * * @param string $colName 集合名 * @param array $query 查詢條件,具體請看 [查詢條件說明文件] * @param string $fields 要取其值的欄位,預設為 "_id" 欄位,類似mysql中的自增主鍵 * * @return mixed */ public function fetchOne($colName,$query=array(), $fields='_id'){ $ret = $this->fetchRow($colName,$query,array($fields)); return isset($ret[$fields]) ? $ret[$fields] : false; } /** * 返回查詢文件集合集中指定欄位的值(一維陣列) * * @param string $colName 集合名 * @param array $query 查詢條件,具體請看 [查詢條件說明文件] * @param string $fields 要取其值的欄位,預設為 "_id" 欄位,類似mysql中的自增主鍵 * * @return array */ public function fetchCol($colName,$query=array(), $fields='_id'){ $result = array(); $list = $this->select($colName,$query,array($fields)); foreach ($list as $row){ $result[] = $row[$fields]; } return $result; } /** * 返回指定下標的查詢文件集合(二維陣列) * * @param string $colName 集合名 * @param array $query 查詢條件,具體請看 [查詢條件說明文件] * @param string $fields 要取其值的欄位,預設為 "_id" 欄位,類似mysql中的自增主鍵 * * @return array */ public function fetchAssoc($colName,$query=array(), $fields='_id'){ $result = array(); $list = $this->select($colName,$query); foreach ($list as $row){ $key = $row[$fields]; $result[][$key] = $row; } return $result; } /* ==================================== 輔助操作介面API ================================= */ /** * 返回命令或命令字首 * * @param string $option 命令,如果為空時則返回命令字首 * * @return string */ public function cmd($option=''){ // 只返回命令字首 if($option == ''){ return $this->_cmd; } // 如果是操作符 if(isset($this->_condMap[$option])){ $option = $this->_condMap[$option]; } return $this->_cmd.$option; } /** * 選擇或建立資料庫(注意:新建立的資料庫如果在關閉連線前沒有寫入資料將會被自動刪除) * * @param string $dbname 資料庫名 */ public function selectDB($dbname){ $this->_db = $this->_mongo->selectDB($dbname); } /** * 得到所有的資料庫 * * @param boolean $onlyName 是否只返回資料庫名的陣列 * @return array */ public function allDB($onlyName=false){ $ary = $this->_mongo->listDBs(); if($onlyName){ $ret = array(); foreach ($ary['databases'] as $row){ $ret[] = $row['name']; } return $ret; }else{ return $ary; } } /** * 刪除資料庫 * * @return array */ public function dropDB($dbname){ return $this->_mongo->dropDB($dbname); } /** * 關閉連線 * */ public function close(){ $this->_mongo->close(); } /** * 得到 Mongo 原生物件,進行其它更高階的操作,詳細請看PHP手冊 * */ public function getMongo(){ return $this->_mongo; } /** * 返回最後的錯誤資訊 * * @return array */ public function getError(){ return $this->_db->lastError(); } /* ======================= 以下為私有方法 ====================== */ // 解析資料組中的'_id'欄位(如果有的話) private function _parseId($arr){ if(isset($arr['_id'])){ $arr['_id'] = new MongoId($arr['_id']); } return $arr; } // 得到集合物件 private function _getCol($colName){ return $this->_db->selectCollection($colName); } // 解析陣列中的"_id"並且返回 private function _parseArr($arr){ if(!empty($arr)) { $ret = (array)$arr['_id']; $arr['_id'] = $ret['$id']; } return $arr; } }//End Class ?>