MongoDB PHP

MongoDB + PHP 实战全攻略(2025 最新版)

核心结论使用 mongodb/mongodb Composer 包 + PECL mongodb 扩展 是 PHP 操作 MongoDB 的 唯一推荐方式


一、环境准备(一键搞定)

# 1. 安装 PECL 扩展(必须)
sudo pecl install mongodb

# 2. 启用扩展(php.ini)
echo "extension=mongodb.so" | sudo tee /etc/php/*/mods-available/mongodb.ini
sudo phpenmod mongodb

# 3. 安装 PHP Library(Composer)
composer require mongodb/mongodb

验证安装成功

php -r "echo class_exists('MongoDB\Client') ? 'OK' : 'FAIL';"
# 输出:OK

二、连接 MongoDB(5 种常见场景)

<?php
require 'vendor/autoload.php';
use MongoDB\Client;

// 1. 本地单节点
$client = new Client("mongodb://127.0.0.1:27017");

// 2. 副本集 + 认证 + 读从节点
$client = new Client(
    "mongodb://user:pass@host1:27017,host2:27017,host3:27017/mydb?
     replicaSet=rs0&authSource=admin&readPreference=secondaryPreferred"
);

// 3. 分片集群(通过 mongos)
$client = new Client("mongodb://mongos1:27017,mongos2:27017");

// 4. 连接池配置(生产必备)
$client = new Client("mongodb://localhost:27017", [
    'maxConnections' => 100,
    'minConnections' => 10,
    'connectTimeoutMS' => 5000,
    'socketTimeoutMS' => 30000,
]);

// 5. Atlas 云数据库
$client = new Client("mongodb+srv://user:pass@cluster0.xxxxx.mongodb.net/mydb");

三、CRUD 完整示例

$collection = $client->selectDatabase('blog')->selectCollection('posts');

// 插入
$insertResult = $collection->insertOne([
    'title' => 'MongoDB + PHP 实战',
    'author' => 'Alice',
    'tags' => ['php', 'mongodb', 'nosql'],
    'created_at' => new MongoDB\BSON\UTCDateTime(),
    'views' => 0
]);
echo "插入ID: " . $insertResult->getInsertedId() . PHP_EOL;

// 查询
$post = $collection->findOne(['title' => 'MongoDB + PHP 实战']);
echo "标题: " . $post->title . PHP_EOL;

// 更新
$collection->updateOne(
    ['_id' => $post->_id],
    ['$inc' => ['views' => 1], '$set' => ['updated_at' => new MongoDB\BSON\UTCDateTime()]]
);

// 删除
$collection->deleteOne(['title' => '旧文章']);

四、聚合查询(Aggregation)

$pipeline = [
    // 匹配已发布文章
    ['$match' => ['status' => 'published']],
    
    // 关联作者信息(类似 JOIN)
    ['$lookup' => [
        'from' => 'users',
        'localField' => 'author_id',
        'foreignField' => '_id',
        'as' => 'author'
    ]],
    ['$unwind' => '$author'],
    
    // 按作者分组统计
    ['$group' => [
        '_id' => '$author.name',
        'article_count' => ['$sum' => 1],
        'total_views' => ['$sum' => '$views']
    ]],
    
    // 排序
    ['$sort' => ['total_views' => -1]],
    
    // 分页
    ['$skip' => 0],
    ['$limit' => 10]
];

$results = $collection->aggregate($pipeline);
foreach ($results as $row) {
    echo "{$row->_id}: {$row->article_count} 篇, {$row->total_views} 浏览\n";
}

五、事务(ACID)

$session = $client->startSession();

try {
    $session->startTransaction();

    // 扣减库存
    $client->inventory->updateOne(
        ['product_id' => 1001],
        ['$inc' => ['stock' => -1]],
        ['session' => $session]
    );

    // 创建订单
    $client->orders->insertOne([
        'product_id' => 1001,
        'quantity' => 1,
        'status' => 'paid',
        'created_at' => new MongoDB\BSON\UTCDateTime()
    ], ['session' => $session]);

    $session->commitTransaction();
    echo "订单创建成功\n";
} catch (Exception $e) {
    $session->abortTransaction();
    echo "事务失败: " . $e->getMessage() . "\n";
} finally {
    $session->endSession();
}

六、GridFS 大文件存储

// 上传文件
$bucket = $client->selectGridFSBucket();
$stream = $bucket->openUploadStream('avatar.jpg', [
    'metadata' => ['contentType' => 'image/jpeg', 'user_id' => 123]
]);
fwrite($stream, file_get_contents('/path/to/avatar.jpg'));
$fileId = $bucket->getFileIdForStream($stream);
fclose($stream);

// 下载文件
$downloadStream = $bucket->openDownloadStream($fileId);
$contents = stream_get_contents($downloadStream);
header('Content-Type: image/jpeg');
echo $contents;

七、Laravel 集成(最优雅)

1. 安装

composer require jenssegers/mongodb

2. 配置 .env

DB_CONNECTION=mongodb
DB_HOST=127.0.0.1
DB_PORT=27017
DB_DATABASE=laravel_db
DB_USERNAME=admin
DB_PASSWORD=secret

3. 模型

use Jenssegers\Mongodb\Eloquent\Model;

class Post extends Model
{
    protected $connection = 'mongodb';
    protected $collection = 'posts';
    protected $fillable = ['title', 'content', 'tags'];

    // 自动处理日期
    protected $dates = ['created_at', 'updated_at'];
}

4. 使用

// 创建
Post::create([
    'title' => 'Laravel + MongoDB',
    'content' => '内容...',
    'tags' => ['laravel', 'mongodb']
]);

// 查询
$posts = Post::where('tags', 'laravel')
             ->orderBy('created_at', 'desc')
             ->paginate(10);

八、性能优化技巧

技巧代码示例
批量操作insertMany() / bulkWrite()
投影字段find($filter, ['projection' => ['title' => 1]])
索引createIndex(['email' => 1], ['unique' => true])
避免 N+1使用 $lookup 或预加载
连接复用全局单例 Client
// 单例模式
class Mongo
{
    private static $client;
    public static function getClient()
    {
        if (!self::$client) {
            self::$client = new Client("mongodb://localhost:27017");
        }
        return self::$client;
    }
}

九、调试与日志

// 开启调试(开发环境)
ini_set('mongodb.debug', 'stderr');

// 查看最后执行的命令
$manager = $client->getManager();
print_r($manager->getServers());

十、完整实战项目结构

project/
├── vendor/
├── src/
│   ├── Models/User.php
│   ├── Services/MongoService.php
│   └── Utils/GridFS.php
├── public/index.php
├── composer.json
└── .env

十一、常见错误与解决方案

错误原因解决方案
Class 'MongoDB\Client' not found未安装 Librarycomposer require mongodb/mongodb
extension 'mongodb' not loadedPECL 未启用检查 php.ini
Authentication failed认证数据库错误?authSource=admin
Transaction not supported单节点部署副本集
Document exceeds 16MB超大文档使用 GridFS

十二、学习资源


你现在可以做什么?

目标一行命令
连接本地 MongoDBnew Client()
插入数据insertOne()
查询数据find()
开启事务startSession()
上传文件GridFS

告诉我你的需求,我给你代码:

  1. 你用 Laravel 还是 原生 PHP
  2. 要实现 用户登录日志系统 还是 文件上传
  3. 数据量多大?是否需要 分片
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

AI老李

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值