MongoDB + PHP 实战全攻略(2025 最新版)
核心结论:使用
mongodb/mongodbComposer 包 + PECLmongodb扩展 是 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 | 未安装 Library | composer require mongodb/mongodb |
extension 'mongodb' not loaded | PECL 未启用 | 检查 php.ini |
Authentication failed | 认证数据库错误 | 加 ?authSource=admin |
Transaction not supported | 单节点 | 部署副本集 |
Document exceeds 16MB | 超大文档 | 使用 GridFS |
十二、学习资源
- 官方文档:MongoDB PHP Library
- Laravel MongoDB:jenssegers/laravel-mongodb
- 示例项目:GitHub Demo
你现在可以做什么?
| 目标 | 一行命令 |
|---|---|
| 连接本地 MongoDB | new Client() |
| 插入数据 | insertOne() |
| 查询数据 | find() |
| 开启事务 | startSession() |
| 上传文件 | GridFS |
告诉我你的需求,我给你代码:
- 你用 Laravel 还是 原生 PHP?
- 要实现 用户登录、日志系统 还是 文件上传?
- 数据量多大?是否需要 分片?

580

被折叠的 条评论
为什么被折叠?



