PHP 8.1+ 连 MongoDB 必须安装官方 mongodb 扩展,使用 MongoDB\Client 并在连接字符串中添加 ?retryWrites=true;find() 返回游标需调用 toArray() 或 foreach 遍历;插入时 _id 必须为 ObjectId 实例。
mongodb 扩展,不是 mongo
老教程常提的 mongo 扩展早在 2018 年就废弃了,PHP 7.4+ 完全不兼容。现在唯一支持的扩展是 mongodb(由 MongoDB 官方维护),它提供 MongoDB\Driver\Manager 和 MongoDB\Client 两类接口。
安装方式取决于你的环境:
pecl install mongodb,然后在 php.ini 加 extension=mongodb
brew install php-mongodb(对应你用的 PHP 版本,如 php81-mongodb)php_mongodb.dll,放进 ext/ 目录并启用装完运行 php -m | grep mongodb 或 phpinfo() 确认扩展已加载。没这步,后面所有代码都会报 Class 'MongoDB\Client' not found。
MongoDB\Client 初始化时连接字符串不能漏 /?retryWrites=true
这是现代 MongoDB 驱动默认要求的写入重试机制,不加会导致连接成功但写操作失败(尤其在副本集或 Atlas 上)。标准连接字符串长这样:
$client = new MongoDB\Client('mongodb://localhost:27017/?retryWrites=true');
常见漏配点:
mongodb://localhost:27017 即可,但建议显式加上 ?retryWrites=true
mongodb://myuser:mypass@localhost:27017/mydb?retryWrites=true,注意密码里如果有特殊字符(如 /、@),必须 URL 编码
?ssl=true&tls=true&retryWrites=true&w=majority,少任意一个参数都可能连不上或写失败find() 返回游标,记得 toArray() 或遍历find() 返回的是 MongoDB\Driver\Cursor 对象,不是数组。直接 print_r($cursor) 只能看到对象结构,看不到实际文档。
正确

$cursor->toArray() —— 适合小数据量,比如查用户列表foreach ($cursor as $doc) { ... } —— 游标自动流式读取,不缓存全部结果$collection->find([], ['limit' => 10]),而不是在 PHP 层用 array_slice()
错误示例:$result = $collection->find(['status' => 'active']); var_dump($result); → 输出是 object(MongoDB\Driver\Cursor)#5,什么文档都看不到。
_id 字段类型必须是 MongoDB\BSON\ObjectId,不能是字符串如果你手动指定 _id,比如 ['_id' => 'abc123', 'name' => 'test'],驱动不会报错,但这个 _id 会被当普通字符串存进去,失去 ObjectId 的时间戳、机器标识等语义,且后续用 ObjectId('abc123') 查询会失败(因为类型不匹配)。
正确写法:
$collection->insertOne(['name' => 'test']) → 返回结果含 $result->getInsertedId() 是 ObjectId 实例$collection->insertOne(['_id' => new MongoDB\BSON\ObjectId('65a1b2c3d4e5f67890123456'), 'name' => 'test'])
if (MongoDB\BSON\ObjectId::isValid($idStr)) { $oid = new MongoDB\BSON\ObjectId($idStr); }
ObjectId 校验和转换这步容易跳过,导致查询静默失败或索引失效,尤其是从 REST API 接收 ID 参数时。