Frequently Asked Questions
On this page
Common Extension Installation Errors
PHP Headers Not Found
For example:
/private/tmp/pear/install/mongodb/php_phongo.c:24:10: fatal error: 'php.h' file not found #include <php.h> ^~~~~~~
This error indicates that PHP's build system cannot find the necessary headers.
All PHP extensions require headers in order to compile. Additionally, those
headers must correspond to the PHP runtime for which the extension will be used.
Generally, the phpize
command (invoked by pecl
) will ensure that the
extension builds with the correct headers.
Note that the mere presence of a PHP runtime does not mean that headers are
available. On various Linux distributions, headers are often published under a
separate php-dev
or php-devel
package. On macOS, the default PHP runtime
does not include headers and users typically need to install PHP (and headers)
via Homebrew in order to build an extension.
Multiple PHP Runtimes Installed
If your system has multiple versions of PHP installed, each version will have
its own pecl
and phpize
commands. Additionally, each PHP runtime may
have separate php.ini
files for each SAPI (e.g. FPM, CLI). If the extension
has been installed but is not available at runtime, double-check that you have
used the correct pecl
command and have modified the appropriate php.ini
file(s).
If there is any doubt about the php.ini
file being used by a PHP runtime,
you should examine the output of phpinfo() for that particular
SAPI. Additionally, php_ini_loaded_file() and
php_ini_scanned_files() may be used to determine
exactly which INI files have been loaded by PHP.
To debug issues with the extension not being loaded, you can use the
detect-extension
script provided in the tools directory. You can run this
script from the CLI or include it in a script accessible via your web server.
The tool will point out potential issues and installation instructions for your
system. Assuming you've installed the library through Composer, you can call the
script from the vendor directory:
php vendor/mongodb/mongodb/tools/detect-extension.php
If you want to check configuration for a web server SAPI, include the file in
a script accessible from the web server and open it in your browser. Remember to
wrap the script in <pre>
tags to properly format its output:
<pre>require(...); </pre>
Loading an Incompatible DLL on Windows
Windows binaries are available for various combinations of PHP version, thread safety (TS or NTS), and architecture (x86 or x64). Failure to select the correct binary will result in an error when attempting to load the extension DLL at runtime:
PHP Warning: PHP Startup: Unable to load dynamic library 'mongodb'
Ensure that you have downloaded a DLL that corresponds to the following PHP runtime properties:
PHP version (
PHP_VERSION
)Thread safety (
PHP_ZTS
)Architecture (
PHP_INT_SIZE
)
In addition to the aforementioned constants, these properties can also be
inferred from phpinfo(). If your system has multiple PHP
runtimes installed, double-check that you are examining the phpinfo()
output
for the correct environment.
The aforementioned detect-extension
script can also be used to determine the
appropriate DLL for your PHP environment.
Connection Handling and Persistence
Connections to the MongoDB deployment are handled by the libmongoc
library and the PHP extension. When you construct
a MongoDB\Client
instance, the PHP library creates a
MongoDB\Driver\Manager instance by using the
same connection string and options. The extension also uses those constructor
arguments to derive a hash key for persistent libmongoc
clients. If
you previously persisted a libmongoc
client by using a key, it is
reused. Otherwise, a new libmongoc
client is created and persisted
for the lifetime of the PHP worker process. You can learn more about
this process in the PHP extension documentation.
Each libmongoc
client maintains its own connections to the MongoDB deployment
and a view of its topology. When you reuse a persistent libmongoc
client, the
PHP library can avoid the overhead of establishing new connections and
rediscovering the topology. This approach generally improves performance and is
the driver's default behavior.
Persistent libmongoc
clients are not freed until the PHP worker process
ends. This means that connections to a MongoDB deployment might remain open
after a MongoDB\Driver\Manager
object goes out of scope. While this is
typically not an issue for applications that connect to one MongoDB deployment,
it might be problematic in some situations, which are described in the
following list:
PHP-FPM is configured with
pm.max_requests=0
, so that workers never respawn, and a PHP application is deployed many times with small changes to its MongoDB connection string or options. This could lead to an accumulation oflibmongoc
client objects in each worker process.An application occasionally connects to a separate MongoDB deployment in a backend component where request latency is not the most important aspect.
In the first case, restarting PHP-FPM as part of the application deployment
allows the application to release any unused libmongoc
clients and still use
a persistent client for the latest connection string.
The second case requires a different solution. Specifying true
for the
disableClientPersistence
driver option instructs the PHP library to
create a new libmongoc
client and ensure it is freed when the corresponding
MongoDB\Driver\Manager
goes out of scope.
The following code demonstrates how to set the
disableClientPersistence
option to true
when creating a client:
$client = new MongoDB\Client( uri: getenv('MONGODB_URI') ?: 'mongodb://127.0.0.1/', uriOptions: [], driverOptions: ['disableClientPersistence' => true], );
Use the disableClientPersistence
driver option after careful
consideration, because opting out of client persistence requires more
time to establish connections to the MongoDB deployment and discover its
topology.
Server Selection Failures
The following are all examples of Server Selection failures:
No suitable servers found (`serverSelectionTryOnce` set): [connection refused calling hello on 'a.example.com:27017'] [connection refused calling hello on 'b.example.com:27017'] No suitable servers found: `serverSelectionTimeoutMS` expired: [socket timeout calling hello on 'example.com:27017'] No suitable servers found: `serverSelectionTimeoutMS` expired: [connection timeout calling hello on 'a.example.com:27017'] [connection timeout calling hello on 'b.example.com:27017'] [TLS handshake failed: -9806 calling hello on 'c.example.com:27017'] No suitable servers found: `serverselectiontimeoutms` timed out: [TLS handshake failed: certificate verify failed (64): IP address mismatch calling hello on 'a.example.com:27017'] [TLS handshake failed: certificate verify failed (64): IP address mismatch calling hello on 'b.example.com:27017']
These errors typically manifest as a MongoDB\Driver\Exception\ConnectionTimeoutException exception from the extension. The actual exception messages originate from libmongoc, which is the underlying system library used by the extension. Since these messages can take many forms, it's helpful to break down the structure of the message so you can better diagnose errors in your application.
Messages will typically start with "No suitable servers found". The next part of
the message indicates how server selection failed. By default, the extension
avoids a server selection loop and instead makes a single attempt (according to
the serverSelectionTryOnce
connection string option). If the extension is
configured to utilize a loop, a message like "serverSelectionTimeoutMS expired"
will tell us that we exhausted its time limit.
The last component of the message tells us why server selection failed, and includes one or more errors directly from the topology scanner, which is the service responsible for connecting to and monitoring each host. Any host that last experienced an error during monitoring will be included in this list. These messages typically originate from low-level socket or TLS functions.
The following is not meant to be exhaustive, but will hopefully point you in the right direction for analyzing the contributing factor(s) for a server selection failure:
"connection refused" likely indicates that the remote host is not listening on the expected port.
"connection timeout" could indicate a routing or firewall issue, or perhaps a timeout due to latency.
"socket timeout" suggests that a connection was established at some point but was dropped or otherwise timed out due to latency.
"TLS handshake failed" suggests something related to TLS or OCSP verification and is sometimes indicative of misconfigured TLS certificates.
In the case of a connection failure, you can use the connect
tool to try and
receive more information. This tool attempts to connect to each host in a
connection string using socket functions to see if it is able to establish a
connection, send, and receive data. The tool takes the connection string to a
MongoDB deployment as its only argument. Assuming you've installed the library
through Composer, you would call the script from the vendor directory:
php vendor/mongodb/mongodb/tools/connect.php mongodb://127.0.0.1:27017
In case the server does not accept connections, the output will look like this:
Looking up MongoDB at mongodb://127.0.0.1:27017 Found 1 host(s) in the URI. Will attempt to connect to each. Could not connect to 127.0.0.1:27017: Connection refused
Note
The tool only supports the mongodb://
URI schema. Using the
mongodb+srv
scheme is not supported.