c5_labsci/zciyphp/dbmongo.php

370 lines
12 KiB
PHP
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

<?php
/* =================================================================================
* License: GPL-2.0 license
* Author: 众产® https://ciy.cn/code
* Version: 0.1.3
* =================================================================================*/
/**
* getone 获取一条数据。 无数据返回null 出错返回false 判断is_array确认数据有效
* get 获取数据集合。 无数据返回array() 出错返回false
* insert 新增数据。 成功返回影响行数 出错返回false
* update 更新数据。 成功返回影响行数 出错返回false
* delete 删除及备份数据。 成功返回影响行数 出错返回false
* begin 开始事务 成功返回true 出错返回false
* commit 事务提交 成功返回true 出错返回false
* rollback 事务回滚 成功返回true 出错返回false
* tran 事务回调 成功返回true 出错返回false
* insert_id 获取刚新增数据的id
*
*
$mongo = new \ciy\dbmongo();
$cmd = new \stdClass();
$cmd->collection = 'movies';
$cmd->pageno = 1;
$count = -1;
$rows = $mongo->get($cmd, $count);
if ($rows === false)
return clog($mongo->error);
clog($count);
foreach ($rows as $row) {
clog($row);
}
return;
*
*/
namespace ciy;
class dbmongo {
private $dbpst;
private $linkdb;
private $session;
private $database;
private $lastinsertid;
private $isTransaction;
public $error;
function __construct($dbpst = '') {
$this->linkdb = false;
$this->dbpst = $dbpst;
$this->isTransaction = false;
$this->error = '';
}
private function errdata($errmsg, $ret = false) {
$this->error = $errmsg;
return $ret;
}
private function connect() {
if ($this->linkdb !== false)
return $this->linkdb;
$cfg = webini('mongodb' . $this->dbpst);
if (is_string($cfg))
return $cfg;
try {
$uriOptions = [];
$driverOptions = [];
$this->linkdb = new \MongoDB\Driver\Manager(
$cfg['uri'],
$uriOptions,
$driverOptions
);
$pingCommand = new \MongoDB\Driver\Command(['ping' => 1]);
$this->linkdb->executeCommand('admin', $pingCommand);
$this->database = $cfg['name'];
return $this->linkdb;
} catch (\Exception $e) {
return 'MongoDB connection failed: ' . $e->getMessage();
}
}
private function getTransactionOptions($defaultOptions = null): array {
if ($this->isTransaction && $this->session) {
return ['session' => $this->session];
}
return $defaultOptions ? ['writeConcern' => $defaultOptions] : [];
}
/**
* 获取查询的第一条数据
*
* @param \stdClass $params 查询参数
* - collection: string 集合名
* - filter: array 查询条件 (可选)
* - options: array 查询选项 (可选)
* @return array|false 查询结果或false表示失败
*/
public function getone(\stdClass $params) {
try {
$link = $this->connect();
if (is_string($link))
return $link;
$params->options = $params->options ?? [];
$params->options['limit'] = 1;
$params->filter = $params->filter ?? [];
$query = new \MongoDB\Driver\Query($params->filter, $params->options);
$cursor = $link->executeQuery(
"{$this->database}.{$params->collection}",
$query,
$this->getTransactionOptions()
);
foreach ($cursor as $document) {
return $document;
}
return null;
} catch (\Exception $e) {
return $this->errdata('Query getone failed: ' . $e->getMessage());
}
}
/**
* 获取查询的多条数据(带分页)
*
* @param \stdClass $params 查询参数
* - collection: string 集合名
* - filter: array 查询条件 (可选)
* - options: array 查询选项 (可选)
* - pageno: int 页码 (默认1)
* - pagecount: int 每页数量 (默认10)
* @return \stdClass|false 包含数据和总数量的对象或false表示失败
*/
public function get(\stdClass $params, &$rowcount = -1) {
try {
$link = $this->connect();
if (is_string($link))
return $link;
$params->filter = $params->filter ?? new \stdClass();
$params->options = $params->options ?? [];
$params->pageno = $params->pageno ?? 1;
$params->pagecount = $params->pagecount ?? 10;
if ($rowcount == -1) {
$countCommand = new \MongoDB\Driver\Command([
'count' => $params->collection,
'query' => $params->filter
]);
$countResult = $link->executeCommand($this->database, $countCommand, $this->getTransactionOptions());
$rowcount = $countResult->toArray()[0]->n ?? 0;
}
$params->options['skip'] = ($params->pageno - 1) * $params->pagecount;
$params->options['limit'] = $params->pagecount;
// 执行查询
$query = new \MongoDB\Driver\Query($params->filter, $params->options);
$cursor = $link->executeQuery(
"{$this->database}.{$params->collection}",
$query,
$this->getTransactionOptions()
);
return $cursor;
} catch (\Exception $e) {
return $this->errdata('Query get failed: ' . $e->getMessage());
}
}
/**
* 插入数据
*
* @param \stdClass $params 插入参数
* - collection: string 集合名
* - document: array 要插入的文档
* - options: array 插入选项 (可选)
* @return int|false 插入数量或false表示失败
*/
public function insert(\stdClass $params) {
if (empty($params->document) || !is_array($params->document)) {
return $this->errdata('Document must be provided and must be an array');
}
try {
$link = $this->connect();
if (is_string($link))
return $link;
$bulk = new \MongoDB\Driver\BulkWrite();
$this->lastinsertid = $bulk->insert($params->document);
$writeConcern = new \MongoDB\Driver\WriteConcern(\MongoDB\Driver\WriteConcern::MAJORITY, 1000);
$writeResult = $link->executeBulkWrite("{$this->database}.{$params->collection}", $bulk, $this->getTransactionOptions($writeConcern));
if ($writeResult === false) {
return $this->errdata('Write Error');
}
return $writeResult->getInsertedCount();
} catch (\Exception $e) {
return $this->errdata('Insert operation failed: ' . $e->getMessage());
}
}
public function insert_id() {
return $this->lastinsertid;
}
/**
* 更新数据
*
* @param \stdClass $params 更新参数
* - collection: string 集合名
* - filter: array 查询条件
* - update: array 更新操作
* - options: array 更新选项 (可选)
* @return int|false 更新的文档数量或false表示失败
*/
public function update(\stdClass $params) {
if (empty($params->filter) || !is_array($params->filter)) {
return $this->errdata('Filter must be provided and must be an array');
}
if (empty($params->update) || !is_array($params->update)) {
return $this->errdata('Update must be provided and must be an array');
}
try {
$link = $this->connect();
if (is_string($link))
return $link;
$bulk = new \MongoDB\Driver\BulkWrite();
$params->options = $params->options ?? [];
if (!isset($params->options['multi'])) {
$params->options['multi'] = false;
}
$bulk->update($params->filter, $params->update, $params->options);
$writeConcern = new \MongoDB\Driver\WriteConcern(\MongoDB\Driver\WriteConcern::MAJORITY, 1000);
$writeResult = $link->executeBulkWrite("{$this->database}.{$params->collection}", $bulk, $this->getTransactionOptions($writeConcern));
if ($writeResult === false) {
return $this->errdata('Write Error');
}
return $writeResult->getModifiedCount();
} catch (\Exception $e) {
return $this->errdata('Update operation failed: ' . $e->getMessage());
}
}
/**
* 删除数据
*
* @param \stdClass $params 删除参数
* - collection: string 集合名
* - filter: array 查询条件
* - options: array 删除选项 (可选)
* @return int|false 删除的文档数量或false表示失败
*/
public function delete(\stdClass $params) {
if (empty($params->filter) || !is_array($params->filter)) {
return $this->errdata('Filter must be provided and must be an array');
}
try {
$link = $this->connect();
if (is_string($link))
return $link;
$bulk = new \MongoDB\Driver\BulkWrite();
$params->options = $params->options ?? [];
if (!isset($params->options['limit'])) {
$params->options['limit'] = false;
}
$bulk->delete($params->filter, $params->options);
$writeConcern = new \MongoDB\Driver\WriteConcern(\MongoDB\Driver\WriteConcern::MAJORITY, 1000);
$writeResult = $link->executeBulkWrite("{$this->database}.{$params->collection}", $bulk, $this->getTransactionOptions($writeConcern));
if ($writeResult === false) {
return $this->errdata('Write Error');
}
return $writeResult->getDeletedCount();
} catch (\Exception $e) {
return $this->errdata('Delete operation failed: ' . $e->getMessage());
}
}
/**
* 开始事务
* @return bool 是否成功
*/
public function begin() {
if ($this->isTransaction) {
return $this->errdata('Transaction already started');
}
try {
$link = $this->connect();
if (is_string($link))
return $link;
$this->session = $link->startSession();
$this->session->startTransaction();
$this->isTransaction = true;
return true;
} catch (\Exception $e) {
return $this->errdata('Failed to start transaction: ' . $e->getMessage());
}
}
/**
* 提交事务
* @return bool 是否成功
*/
public function commit() {
if (!$this->isTransaction) {
return $this->errdata('No active transaction to commit');
}
try {
$this->session->commitTransaction();
$this->session->endSession();
$this->isTransaction = false;
return true;
} catch (\Exception $e) {
$this->isTransaction = false;
return $this->errdata('Failed to commit transaction: ' . $e->getMessage());
}
}
/**
* 回滚事务
* @return bool 是否成功
*/
public function rollback() {
if (!$this->isTransaction) {
return $this->errdata('No active transaction to rollback');
}
try {
$this->session->abortTransaction();
$this->session->endSession();
$this->isTransaction = false;
return true;
} catch (\Exception $e) {
$this->isTransaction = false;
return $this->errdata('Failed to rollback transaction: ' . $e->getMessage());
}
}
public function tran($func) {
if (!($func instanceof \Closure)) {
$this->error = '没有传递正确的闭包函数';
return false;
}
$this->begin();
$ret = false;
try {
$ret = $func();
} catch (\Exception $ex) {
$ret = false;
$this->error = $ex->getMessage();
}
if ($ret === false)
$this->rollback();
else
$this->commit();
return $ret;
}
}