This commit is contained in:
Your Name
2026-04-21 01:02:21 +08:00
parent e568577ce0
commit b943ea2ab7
8 changed files with 1119 additions and 14 deletions

View File

@@ -0,0 +1,187 @@
<?php
declare(strict_types=1);
namespace db\mongo;
use MongoDB\Client;
use MongoDB\Collection;
use MongoDB\Database;
use MongoDB\Driver\Exception\Exception as MongoDriverException;
use MongoDB\Operation\FindOneAndUpdate;
class MongoBase
{
private static ?self $instance = null;
private Client $client;
private Database $db;
public static function getInstance(): self
{
if (self::$instance === null) {
self::$instance = new self();
}
return self::$instance;
}
public function __construct()
{
$config = $this->getMongoConfig();
$this->client = $this->buildClient($config);
$this->db = $this->client->selectDatabase((string) $config['database']);
}
public function getDb(): Database
{
return $this->db;
}
public function getNextSequence(string $strCollection, string $strSequenceName): int
{
$result = $this->getCollection($strCollection)->findOneAndUpdate(
['_id' => $strSequenceName],
['$inc' => ['sequence_value' => 1]],
[
'upsert' => true,
'returnDocument' => FindOneAndUpdate::RETURN_DOCUMENT_AFTER,
] + $this->getTypeMapOptions()
);
return (int) ($result['sequence_value'] ?? 1);
}
public function insertOne(string $strCollection, array $arrData, array $arrOptions = []): mixed
{
$result = $this->getCollection($strCollection)->insertOne($arrData, $arrOptions);
return $result->getInsertedId();
}
public function insertMany(string $strCollection, array $arrData, array $arrOptions = []): int
{
$result = $this->getCollection($strCollection)->insertMany($arrData, $arrOptions);
return $result->getInsertedCount();
}
public function findOne(string $strCollection, array $arrFilter = [], array $arrOptions = []): ?array
{
$result = $this->getCollection($strCollection)->findOne(
$arrFilter,
$arrOptions + $this->getTypeMapOptions()
);
return $result === null ? null : (array) $result;
}
public function findMany(
string $strCollection,
array $arrFilter = [],
int $intCount = 0,
array $arrSort = [],
array $arrOptions = []
): array {
$options = $arrOptions + $this->getTypeMapOptions();
if ($intCount > 0 && !isset($options['limit'])) {
$options['limit'] = $intCount;
}
if ($arrSort !== [] && !isset($options['sort'])) {
$options['sort'] = $arrSort;
}
$cursor = $this->getCollection($strCollection)->find($arrFilter, $options);
$arrResult = [];
foreach ($cursor as $item) {
$arrResult[] = (array) $item;
}
return $arrResult;
}
public function updateOne(string $strCollection, array $arrFilter, array $arrUpdate, array $arrOptions = []): int
{
$result = $this->getCollection($strCollection)->updateOne($arrFilter, $arrUpdate, $arrOptions);
return $result->getModifiedCount();
}
public function delete(string $strCollection, array $arrFilter, array $arrOptions = []): int
{
$result = $this->getCollection($strCollection)->deleteMany($arrFilter, $arrOptions);
return $result->getDeletedCount();
}
private function getCollection(string $strCollection): Collection
{
return $this->db->selectCollection($strCollection);
}
private function getMongoConfig(): array
{
$config = \config('mongodb');
if (!is_array($config)) {
throw new \RuntimeException('MongoDB config is missing.');
}
$config['hostname'] = (string) ($config['hostname'] ?? '127.0.0.1');
$config['hostport'] = (string) ($config['hostport'] ?? '27017');
$config['username'] = (string) ($config['username'] ?? '');
$config['password'] = (string) ($config['password'] ?? '');
$config['database'] = (string) ($config['database'] ?? '');
if ($config['database'] === '') {
throw new \RuntimeException('MongoDB database is not configured.');
}
return $config;
}
private function buildClient(array $config): Client
{
$uri = sprintf('mongodb://%s:%s', $config['hostname'], $config['hostport']);
$options = [];
if ($config['username'] !== '') {
$options['username'] = $config['username'];
$options['password'] = $config['password'];
foreach ($this->getAuthSources($config['database']) as $authSource) {
try {
$client = new Client($uri, $options + ['authSource' => $authSource]);
foreach ($client->selectDatabase($config['database'])->listCollections([], ['maxTimeMS' => 3000]) as $_) {
break;
}
return $client;
} catch (MongoDriverException) {
}
}
throw new \RuntimeException('MongoDB authentication failed for all configured authSource values.');
}
return new Client($uri, $options);
}
private function getAuthSources(string $database): array
{
$sources = [];
$envSource = \env('MONGO_AUTH_DB', '');
if (is_string($envSource) && $envSource !== '') {
$sources[] = $envSource;
}
$sources[] = 'admin';
$sources[] = $database;
return array_values(array_unique($sources));
}
private function getTypeMapOptions(): array
{
return [
'typeMap' => [
'root' => 'array',
'document' => 'array',
'array' => 'array',
],
];
}
}