1. 程式人生 > >MongoDB for PHP擴充套件操作類

MongoDB for PHP擴充套件操作類

  1. <?php  
  2. /** 
  3.  *   
  4. * @link        https://github.com/thendfeel/TmongoDB 
  5. * @example       
  6. * @copyright     
  7. * @site        http://www.uacool.com 
  8. * @created     2013-12-13 
  9. * 
  10. * Manual 
  11. * http://us2.php.net/mongo 
  12. * 針對阿里雲MongoDB資料庫 
  13. * SQL to Mongo Mapping Chart 
  14. * http://us2.php.net/manual/en/mongo.sqltomongo.php 
  15. * 單例模式(只針對相同的config)
     
  16. */
  17. class TmongoDB  
  18. {  
  19.     protected$_db = 'test';  
  20.     protected$_collection = 'user';  
  21.     protected$_validate = array();  
  22.     protectedstatic$_mongoObj = array();  
  23.     private$_exeResult = null;  
  24.     protected$_sql = array();  
  25.     protected$_mongo = null;   
  26.     const CONNECT_DB = 'admin'// 連線資料庫,預設為admin
  27.     /** 
  28.      * Config For MongDB 
  29.      * 
  30.      * @var array 
  31.      */
  32.     protected$_config = array(  
  33.             'mongo_seed1' => 'localhost',  
  34.             'mongo_seed2' => '',  
  35.             'mongo_replname' => '',  
  36.             'mongo_user' => NULL,  
  37.             'mongo_pwd' => NULL  
  38.     );  
  39.     publicfunction __construct($config,$db$collection)  
  40.     {  
  41.         foreach ($this->_config as$k => $v) {  
  42.             if(isset($config[$k])){  
  43.                 $this->_config[$k] = $config[$k];  
  44.             } else {  
  45.                 E('mongoDB資料庫連線,請傳遞'.$k);  
  46.             }  
  47.         }  
  48.         $this->_db = $db;  
  49.         $this->_collection = $collection;  
  50.         $this->init();  
  51.     }  
  52.     publicfunction getMongo()  
  53.     {  
  54.         return$this->_mongo;  
  55.     }  
  56.     /** 
  57.      * Init The Class 
  58.      * 對於相同的配置只初始化一次 
  59.      * @param string $db 
  60.      * @param string $collection 
  61.      */
  62.     publicfunction init()  
  63.     {  
  64.         $config = $this->_config;  
  65.         ksort($config);  
  66.         $encryptStr = '';  
  67.         foreach ($configas$k => $v) {  
  68.             $encryptStr .= ($k.$v);  
  69.         }  
  70.         $key = md5($encryptStr);  
  71.         if (!self::$_mongoObj[$key]) {  
  72.             /*$conStr = "mongodb://"; 
  73.             if ($config['user'] && $config['password']) { 
  74.                 $conStr .= "{$config['user']}:{$config['password']}@"; 
  75.             } 
  76.             $conStr .= "{$config['host']}:{$config['port']}"; 
  77.             $_mongoDB = new \Mongo($conStr, array( 
  78.                     "connect" => false 
  79.             ));*/
  80.             $demo_uri = 'mongodb://' . $config['mongo_user'] . ':' . $config['mongo_pwd'] . '@' .  
  81.                     $config['mongo_seed1'] . ',' . $config['mongo_seed2'] . '/' . self::CONNECT_DB . '?replicaSet=' . $config['mongo_replname'];  
  82.             $manager = new \MongoDB\Driver\Manager($demo_uri);  
  83.             self::$_mongoObj[$key] = $this->_mongo = $manager;  
  84.             /*if ($db && $collection) { 
  85.                 $this->_mongoDB = $_mongoDB->selectCollection($db, $collection); 
  86.             } else { 
  87.                 $this->_mongoDB = $_mongoDB->selectCollection($this->_db,$this->_collection); 
  88.             }*/
  89.         } else {   
  90.             $this->_mongo = self::$_mongoObj[$key];  
  91.         }  
  92.     }  
  93.     /** 
  94.      * Set Db & Collection 
  95.      * 重新設定資料庫和資料表 
  96.      * @param string $db 
  97.      * @param string $collection 
  98.      */
  99.     publicfunction setDb($db = NULL, $collection = NULL)  
  100.     {  
  101.         if ($db) {  
  102.             $this->_db = $db;  
  103.             //$this->_mongoDB = NULL;
  104.             //$this->_mongoDB = $this->_mongoObj->selectCollection($this->_db,$this->_collection);
  105.         }  
  106.         if ($collection) {  
  107.             $this->_collection = $collection;  
  108.         }  
  109.         return$this;  
  110.     }  
  111.     /** 
  112.      * Set Collection 
  113.      * 重新設定資料表 
  114.      * @param string $collection 
  115.      */
  116.     publicfunction setCollection($collection = NULL)  
  117.     {  
  118.         if ($collection) {  
  119.             $this->_collection = $collection;  
  120.             //$this->_mongoDB = NULL;
  121.             //$this->_mongoDB = $this->_mongoObj->selectCollection($this->_db,$collection);
  122.         }  
  123.         return$this;  
  124.     }  
  125.     /** 
  126.      * 獲取指定條件下的集合裡的資料數量,預設使用_id主鍵欄位 
  127.      */
  128.     publicfunctioncount($argv = array(),$fields = '_id')  
  129.     {  
  130.         $result = $this->find($argv,$fields);  
  131.         if ($result) {  
  132.             returncount($result);  
  133.         } else {  
  134.             return 0;  
  135.         }  
  136.     }  
  137.     /** 
  138.      * Fetch From Mongodb 
  139.      * 
  140.      * @param array $argv 
  141.      * @param number $skip 
  142.      * @param number $limit 
  143.      * @param array $sort 
  144.      * @return Ambigous <multitype:, multitype:>|boolean 
  145.      */
  146.     publicfunction find($argv = array(),$fields = array(),$sort = array(),$skip = 0, $limit = 0)  
  147.     {  
  148.         /*$argv = $this->validate($argv); 
  149.         if ($argv) { 
  150.             $result = $this->_mongoDB->find($argv) 
  151.             ->skip($skip) 
  152.             ->limit($limit) 
  153.             ->sort($sort); 
  154.             return self::toArray($result); 
  155.         }*/
  156.         $options = array();  
  157.         if ($skip) {  
  158.             $options['skip'] = $skip;  
  159.         }  
  160.         if ($limit) {  
  161.             $options['limit'] = $limit;  
  162.         }  
  163.         if ($sort) {  
  164.             $options['sort'] = $sort;  
  165.         }  
  166.         if ($fields) {  
  167.             if (is_string($fields)) {  
  168.                 $fields = explode(','$fields);  
  169.             }  
  170.             foreach ($fieldsas$v) {  
  171.                 $options['projection'][$v] = 1;  
  172.             }  
  173.         }   
  174.         $query = new \MongoDB\Driver\Query($argv$options);   
  175.         $cursor = $this->_mongo->executeQuery($this->_db.'.'.$this->_collection, $query);  
  176.         return$cursor->toArray();  
  177.     }  
  178.     /** 
  179.      * 執行命令 
  180.      */
  181.     publicfunction runCommand($command = array())  
  182.     {  
  183.         if (!$command) {  
  184.             return false;  
  185.         }  
  186.         $commandObj = new \MongoDB\Driver\Command($command);  
  187.         try {  
  188.             $cursor = $this->_mongo->executeCommand($this->_db, $commandObj);  
  189.             $response = $cursor->toArray();  
  190.         } catch(\MongoDB\Driver\Exception $e) {  
  191.             echo'Mongo的runCommand異常:',$e->getMessage();  
  192.             exit;  
  193.         }  
  194.         if (count($response) > 1) {  
  195.             return$response;  
  196.         } else {  
  197.             return$response[0];  
  198.         }  
  199.     }  
  200.     /** 
  201.      * Fetch By MongoId 
  202.      * 
  203.      * @param string $_id 
  204.      * @return Ambigous <Ambigous, boolean, multitype:> 
  205.      */
  206.     publicfunction findById($_id = '',$fields = array())  
  207.     {  
  208.         if (is_string($_id)) {  
  209.             return$this->findOne(array('_id' => new \MongoDB\BSON\ObjectID($_id)),$fields);  
  210.         }  
  211.     }  
  212.     /** 
  213.      * Fetch One From MongoDB 
  214.      * 
  215.      * @param array $argv 
  216.      * @param array $fields 
  217.      * @return multitype: boolean 
  218.      */
  219.     publicfunction findOne($argv = array(),$fields = array(),$sort = array())  
  220.     {  
  221.         $result = $this->find($argv,$fields,$sort,0,1);  
  222.         if ($result) {  
  223.             return$result[0];  
  224.         } else {  
  225.             return NULL;  
  226.         }  
  227.             //return $this->cleanId($this->_mongoDB->findOne($argv, $fields));
  228.     }  
  229.     /** 
  230.     * Update MongoDB By Id 
  231.     * 通過主鍵ID更新 
  232.     * @param string $_id 
  233.     * @param array $newData 
  234.     */
  235.     publicfunction updateById($_id$set = array())  
  236.     {  
  237.         return$this->updateStatement(array('_id' => new \MongoDB\BSON\ObjectID($_id)), array('$set'=>$set))->execute()->getModifiedCount();  
  238.     }  
  239.     /** 
  240.     * 執行新增,刪除,更新 All From Mongodb,執行多個語句 
  241.     * $obj->deleteStatement(array('name'=>'1'))->deleteStatement(array('id'=>1))->remove(); 
  242.     * @param array $argv 
  243.     */
  244.     publicfunction execute()  
  245.     {  
  246.         if (!$this->_sql) {  
  247.             return NULL;  
  248.         }  
  249.         $bulk = new \MongoDB\Driver\BulkWrite;  
  250.         foreach ($this->_sql as$val) {  
  251.             switch ($val['type']) {  
  252.                 case'delete':  
  253.                     $bulk->delete($val['sql'],$val['limit']);  
  254.                     break;  
  255.                 case'insert':  
  256.                     $bulk->insert($val['document']);  
  257.                     break;  
  258.                 case'update':  
  259.                     $bulk->update($val['filter'],$val['set'],$val['options']);  
  260.                     break;  
  261.             }  
  262.         }  
  263.         $writeConcern = new \MongoDB\Driver\WriteConcern(\MongoDB\Driver\WriteConcern::MAJORITY, 1000);  
  264.         try {  
  265.             $this->_exeResult = $this->_mongo->executeBulkWrite($this->_db.'.'.$this->_collection, $bulk$writeConcern);  
  266.         } catch(\MongoDB\Driver\Exception\WriteException $e) {  
  267.             echo'MongoDB擴充套件寫入異常:';  
  268.             $writeResult = $e->getWriteResult();  
  269.             if ($writeConcernError = $writeResult->getWriteConcernError()) {    
  270.                 echo$writeConcernError[0]->getMessage(),'<br />';  
  271.             }  
  272.             if ($writeErrors = $writeResult->getWriteErrors()) {   
  273.                 echo$writeErrors[0]->getMessage();  
  274.             }  
  275.             exit();  
  276.         } catch (\MongoDB\Driver\Exception\InvalidArgumentException $e) {  
  277.             exit('MongoDB擴充套件傳入引數異常:'.$e->getMessage());  
  278.         } catch (\MongoDB\Driver\Exception\RuntimeException $e) {  
  279.             exit('MongoDB擴充套件執行異常:'.$e->getMessage());  
  280.         } catch (\MongoDB\Driver\Exception\ExecutionTimeoutException $e) {  
  281.             exit('MongoDB擴充套件執行超時異常:'.$e->getMessage());  
  282.         } catch (\MongoDB\Driver\Exception\ConnectionTimeoutException $e) {  
  283.             exit('MongoDB擴充套件連線超時異常:'.$e->getMessage());  
  284.         } catch (\Exception $e) {  
  285.             exit('系統異常:'.$e->getMessage());  
  286.         }  
  287.         return$this;  
  288.     }  
  289.     /** 
  290.      * 獲取刪除的行數 
  291.      */
  292.     publicfunction getDeletedCount()  
  293.     {  
  294.         if ($this->_exeResult) {  
  295.             return$this->_exeResult->getDeletedCount();  
  296.         } else {  
  297.             return 0;  
  298.         }  
  299.     }  
  300.     /** 
  301.      * 獲取實際更新的行數 
  302.      */
  303.     publicfunction getModifiedCount()  
  304.     {  
  305.         if ($this->_exeResult) {  
  306.             return$this->_exeResult->getModifiedCount();  
  307.         } else {  
  308.             return 0;  
  309.         }  
  310.     }  
  311.     /** 
  312.      * 一次最多插入9萬條以下.耗時 
  313.      * 獲取實際插入的行數 
  314.      */
  315.     publicfunction getInsertedCount()  
  316.     {  
  317.         if ($this->_exeResult) {  
  318.             return$this->_exeResult->getInsertedCount();  
  319.         } else {  
  320.             return 0;  
  321.         }  
  322.     }  
  323.     /** 
  324.      * 獲取實際匹配的行數 
  325.      */
  326.     publicfunction getMatchedCount()  
  327.     {  
  328.         if ($this->_exeResult) {  
  329.             return$this->_exeResult->getMatchedCount();  
  330.         } else {  
  331.             return 0;  
  332.         }  
  333.     }  
  334.     /** 
  335.      * 獲取實際更新失敗然後新插入的行數 
  336.      *  
  337.      */
  338.     publicfunction getUpsertedCount()  
  339.     {  
  340.         if ($this->_exeResult) {  
  341.             return$this->_exeResult->getUpsertedCount();  
  342.         } else {  
  343.             return 0;  
  344.         }  
  345.     }  
  346.     /** 
  347.      * 獲取實際更新失敗然後新插入的ID列表 
  348.      */
  349.     publicfunction getUpsertedIds()  
  350.     {  
  351.         if ($this->_exeResult) {  
  352.             return$this->_exeResult->getUpsertedIds();  
  353.         } else {  
  354.             return 0;  
  355.         }  
  356.     }  
  357.     /** 
  358.      * delete子句 
  359.      * @param $delete 為刪除過濾條件,為陣列形式 
  360.      */
  361.     publicfunction deleteStatement($delete,$limit = 0)  
  362.     {  
  363.         $this->_sql[] = array('type'=>'delete','sql'=>$delete,'limit'=>array('limit'=>$limit));  
  364.         return$this;  
  365.     }  
  366.     /** 
  367.      * insert子句 
  368.      * @param $batch 批量插入資料 
  369.      */
  370.     publicfunction insertStatement($insert,$batch = false)  
  371.     {  
  372.         if ($batch) {  
  373.             if (is_array($insert) && $insert) {  
  374.                 foreach ($insertas$val) {  
  375.                     $this->_sql[] = array('type'=>'insert','document'=>$val);   
  376.                 }  
  377.             }  
  378.         } else {  
  379.             $this->_sql[] = array('type'=>'insert','document'=>$insert);  
  380.         }  
  381.         return$this;  
  382.     }  
  383.     /** 
  384.      * update子句 
  385.      * @param option multi 為true則更新全部符合條件的文件,否則只更新一個符合條件的文件 
  386.      *              upsert 為true則當沒有符合條件的文件時將更新過後的資料插入到集合中 
  387.      * 參考連線:http://blog.csdn.net/qq1355541448/article/details/9082225 
  388.      * 第二個引數有以下的做法: 
  389.      *  修改更新   
  390.      *      使用set關鍵字: $set:讓某節點等於給定值 ,欄位不變,內容變了 
  391.      *  替換更新: 
  392.      *      第一個引數$where=array(‘column_name’=>’col709′),第二個引數:$newdata=array(‘column_exp’=>’HHHHHHHHH’,'column_fid’=>123); 
  393.      *      那麼指定的column_name欄位將會替換成成column_exp(=HHHHHHHHH)和column_fid(123) 
  394.      *  自動累加或自動累減 
  395.      *      array(‘$set’=>$newdata,’$inc’=>array(’91u’=>-5),第二個引數,在找到的91u欄位的引數會自動在原值減5 
  396.      *  刪除指定欄位 
  397.      *      $where=array(‘column_name’=>’col685′); 
  398.      *      $result=$collection->update($where,array(‘$unset’=>’column_exp’));column_exp欄位將會被刪除 
  399.      * 參考文件:https://docs.mongodb.org/manual/reference/operator/update/ 
  400.      */
  401.     publicfunction updateStatement($filter,$set,$options = array('multi' => true, 'upsert' => false))  
  402.     {  
  403.         $this->_sql[] = array('type'=>'update','filter'=>$filter,'set'=>$set,'options'=>$options);  
  404.         return$this;  
  405.     }  
  406.     /** 
  407.     * Remove By Id From Mongodb 
  408.     * 
  409.     * @param string $_id 
  410.     * @return Ambigous <boolean, multitype:> 
  411.     */
  412.     publicfunction removeById($_id)  
  413.     {  
  414.         return$this->deleteStatement(array('_id' => new \MongoDB\BSON\ObjectID($_id)))->execute()->getDeletedCount();  
  415.     }  
  416.     /** 
  417.     * Remove One From Mongodb 
  418.     * 
  419.     * @param array $argv 
  420.     */
  421.     publicfunction removeOne($argv = array())  
  422.     {  
  423.         return$this->deleteStatement($argv,1)->execute()->getDeletedCount();  
  424.     }  
  425.      /** 
  426.      * Remove Field From MongoDB 
  427.      * 
  428.      * @param string $_id 
  429.      * @param array $field 
  430.      */
  431. //  public function removeFieldById($_id, $field = array())
  432. //  {
  433. //      return $this->updateStatement(array('_id' => new \MongoDB\BSON\ObjectID($_id)), array('$unset' => $unSetfield));
  434. //  }
  435.     /** 
  436.     * Validate Data Callbak Function 沒有用到的函式 
  437.     * 
  438.     * @param array $argv 
  439.      */
  440.     privatefunction validate($data)  
  441.     {  
  442.         if ($this->_validate) {  
  443.             foreach ($this->_validate as$arg => $validate) {  
  444.                 if (is_array($data) && array_key_exists(strval($arg), $data)) {  
  445.                     foreach ($validateas$key => $value) {  
  446.                         switch (strtolower($key)) {  
  447.                             case'type':  
  448.                                 if ($value == 'int') {  
  449.                                     $data[$arg] = (int) $data[$arg];  
  450.                                 } elseif ($value == 'string') {  
  451.                                     $data[$arg] = (string) $data[$arg];  
  452.                                 } elseif ($value == 'bool') {  
  453.                                     $data[$arg] = (bool) $data[$arg];  
  454.                                 } elseif ($value == 'float') {  
  455.                                     $data[$arg] = (float) $data[$arg];  
  456.                                 } elseif ($value == 'array') {  
  457.                                     $data[$arg] = (array$data[$arg];  
  458.                                 }  
  459.                                 break;  
  460.                             case'min':  
  461.                                 if (strlen($data[$arg]) < $value) {  
  462.                                     exit('Error: The length of ' . $arg . ' is not matched');  
  463.                                 }  
  464.                                 break;  
  465.                             case'max':  
  466.                                 if (strlen($data[$arg]) > $value) {  
  467.                                     exit('Error: The length of ' . $arg . ' is not matched');  
  468.                                 }  
  469.                                 break;  
  470.                             case'func':  
  471.                                 $call = preg_split('/[\:]+|\-\>/i'$value);  
  472.                                 if (count($call) == 1) {  
  473.                                     $data[$arg] = call_user_func($call['0'], $data[$arg]);  
  474.                                 } else {  
  475.                                     $data[$arg] = call_user_func_array(array($call['0'],$call['1']), array($data[$arg]));  
  476.                                 }  
  477.                                 break;  
  478.                         }  
  479.                     }  
  480.                 }  
  481.             }  
  482.         }  
  483.         return$data;  
  484.     }