在早期 PHP MongoDB 驅動(legacy mongo extension)中,MongoCursor 是處理大量查詢結果的核心物件。本文分析一個基於 Zend Framework 封裝的 Hrs_Mongo_Table 抽象類,展示其透過 find() 與 look() 兩種方法獲取游標的不同設計模式。
Hrs_Mongo_Config 負責管理 MongoDB 連線參數、建立連線與選擇資料庫:
class Hrs_Mongo_Config {
const DEFAULT_HOST = 'localhost';
const DEFAULT_PORT = 27017;
private static $options = ['connect' => true, 'timeout' => 30];
public static $conn = '';
public static $defaultDb = '';
public static $linkStatus = '';
public static function set($server = 'mongodb://localhost:27017', $options = ['connect' => true]) { /* ... */ }
public static function selectDB($database) { /* ... */ }
}
Hrs_Mongo_Table 為抽象基類,封裝 CRUD 操作與游標獲取:
abstract class Hrs_Mongo_Table {
protected $_db = '';
protected $_name = '';
protected $_data = [];
protected $c_options = ['fsync' => true, 'safe' => true];
protected $u_options = ['multiple' => true, 'fsync' => true, 'safe' => true];
protected $d_options = ['fsync' => true, 'justOne' => false, 'safe' => true];
public function __construct() {
if (Hrs_Mongo_Config::$conn instanceof Mongo) {
$this->_db = Hrs_Mongo_Config::$defaultDb->{$this->_name};
} else {
throw new Zend_Exception('MongoDB 伺服器連線失敗');
}
}
// insert, update, delete, dropMe 等方法...
}
此方法不儲存結果至 _data,直接回傳 MongoCursor 物件,適合大量資料分批處理:
public function look($where = [], $fields = []) {
if ($this->testLink()) {
if ($fields) {
return $where ? $this->_db->find($where, $fields) : $this->_db->find()->fields($fields);
} else {
return $where ? $this->_db->find($where) : $this->_db->find();
}
}
return false;
}
呼叫方式: $cursor = $table->look(['status' => 1]); foreach ($cursor as $doc) { ... }
此模式將游標暫存於 _data 屬性,再由 getCursor() 取出:
public function find($where = [], $field = []) {
if ($this->testLink()) {
$this->_data = $this->_db->find($where, $field)->sort(['_id' => -1]);
}
return $this; // 支援鏈式呼叫
}
public function getCursor() {
return $this->_data; // 回傳 MongoCursor 物件
}
呼叫方式: $table->find(['status' => 1])->getCursor();
| 特性 | look() 直接回傳 | find() + getCursor() |
|---|---|---|
| 回傳值 | MongoCursor 物件 | Table 物件本身(鏈式),再呼叫 getCursor() |
| 記憶體佔用 | 低(游標惰性載入) | 相同,但 _data 持有游標參考 |
| 排序/限制 | 需在 find() 參數中指定 | 可在 find() 內鏈式呼叫 sort(), limit() |
| 適用場景 | 單次查詢、直接遍歷 | 需鏈式操作、複雜查詢建構 |
mongodb/mongodb 官方函式庫(PHPLIB),API 差異極大。snapshot() 方法在新版驅動中已移除,查詢一致性改由交易控制。