必须用mongodb扩展(非废弃的mongo),通过MongoDB\Client连接,注意URI格式、BSON类型(如ObjectId、UTCDateTime)、游标需遍历或toArray(),连接应复用,避免OOM或连接耗尽。

PHP 要真正用好 MongoDB,不是装个扩展、连上就完事——关键在连接复用、BSON 类型处理、游标内存控制这三处,踩错一个,线上就 OOM 或连接耗尽。
如何确认 mongodb 扩展已正确加载并可用
很多人卡在这一步却以为是代码写错了。最直接的验证方式不是跑 CRUD 示例,而是查 PHP 自身状态:
- 运行
php -m | grep mongo,输出含mongodb(不是mongo)才表示扩展已加载 - 检查
phpinfo()页面里有没有 “mongodb” 模块区块,重点看 “Version” 和 “Directives” 是否正常 - 若用 Docker,确认容器内
/usr/local/etc/php/conf.d/docker-php-ext-mongodb.ini存在且内容为extension=mongodb.so - Windows 用户注意:
php_mongodb.dll必须与 PHP 架构(x64/x86)、线程安全(TS/NTS)完全匹配,否则extension_loaded('mongodb')永远返回 false
new MongoDB\Client() 的 URI 写法与常见报错
URI 看似简单,但权限、认证机制、拓扑选项稍有偏差就会触发模糊错误,比如 MongoDBDriverException\ConnectionTimeoutException 或静默失败。
- 本地无认证:用
"mongodb://127.0.0.1:27017",别写localhost(某些 DNS 配置下会走 IPv6 导致超时) - 带用户名密码:必须 URL 编码账号密码,例如密码含
@或/时,要用rawurlencode()处理后再拼接 - 生产环境务必加选项:如
"mongodb://user:pass@host:27017/?maxPoolSize=50&minPoolSize=5&connectTimeoutMS=3000",否则默认池大小为 100,小内存机器极易端口占满 - 遇到
Failed to connect to 127.0.0.1:27017: Connection refused,先确认mongod进程是否运行、bindIp 是否允许本机连接(netstat -tuln | grep 27017)
insertOne() 与 find() 中容易忽略的 BSON 类型陷阱
PHP 数组直接传给 MongoDB 看似无缝,但时间、ObjectId、嵌套文档这些类型不显式构造,会导致查询失败或数据错乱。
立即学习“PHP免费学习笔记(深入)”;
-
new MongoDB\BSON\ObjectId()必须用于插入 _id 字段,否则驱动自动生成的 ObjectId 是字符串而非 BSON 对象,后续用findOne(['_id' => new ObjectId($id)])查不到 - 日期必须用
new MongoDB\BSON\UTCDateTime(strtotime('2025-01-01') * 1000),不能传 PHPDateTime对象或时间戳整数 - 查询嵌套字段如
address.city,要确保插入时该路径存在;若字段为null或未设置,find(['address.city' => 'Beijing'])不会命中 - 用
find()返回的是MongoDB\Driver\Cursor对象,不是数组——直接foreach可以,但count($cursor)会报错,需用$cursor->toArray()或配合iterator_count()
避免内存爆炸:大数据量查询必须控制游标行为
这是线上最常被忽视的性能雷区。不设限地 find([])->toArray() 查几万条文档,PHP 进程瞬间吃光内存。
- 永远优先用
limit()和skip()分页,但注意 skip 性能随偏移量增大而陡降 - 真要遍历全量数据,用
batchSize(100)控制每次从服务端拉取数量:$collection->find([], ['batchSize' => 100]) - 聚合操作(
aggregate())务必在管道前端加$match过滤,否则整个集合先载入内存再计算 - 连接对象(
$client)应作为全局或容器单例复用,绝不要在循环或请求中反复new MongoDB\Client(),否则连接池失控
MongoDB 在 PHP 里不是“另一个数据库”,它是文档模型 + BSON 类型系统 + 游标流式语义的组合体。少一个环节对齐,就可能让查询变慢十倍,或让某次更新静默失效。



















