Docs Menu
Docs Home
/ / /
PHP Library Manual

Frequently Asked Questions

On this page

  • Common Extension Installation Errors
  • PHP Headers Not Found
  • Multiple PHP Runtimes Installed
  • Loading an Incompatible DLL on Windows
  • Connection Handling and Persistence
  • Server Selection Failures

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.

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><?php require(...); ?></pre>

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.

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 of libmongoc 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:

<?php
$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.

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.

Back

Upgrade