Checking the loaded PHP extension set is one of the fastest ways to explain why database drivers, archive support, image processing, or outbound HTTP features are missing even when the interpreter itself still starts. A quick module check confirms whether the runtime that actually executes the code exposes the capability an application, script, or health check expects.
The PHP CLI can report active extensions in a few complementary ways. The -m switch prints the built-in and loaded PHP and Zend modules for the current binary, –ri shows the configuration block that phpinfo() exposes for one loaded extension, and extension_loaded() can return a direct loaded or not-loaded result inside an inline php -r check.
Extension state is tied to the SAPI that runs the code. The CLI binary, PHP-FPM pools, and the Apache module can each load different php.ini files and additional .ini fragments, so a module shown by php -m is authoritative only for that runtime. When the shell result and the web result do not match, compare the active configuration files before enabling or disabling anything.
$ php -m [PHP Modules] bcmath bz2 calendar Core ctype curl date dba dom exif filter json mbstring openssl PDO Phar [... additional PHP modules omitted ...] [Zend Modules] Zend OPcache
The output includes built-in modules, shared extensions loaded from the active configuration tree, and a separate Zend section for Zend extensions such as Zend OPcache. The exact module list varies by build and loaded configuration files.
$ php -m | grep --ignore-case '^curl$' curl
The exact-name pattern avoids partial matches such as curl_multi. No output means the current runtime did not load that module.
$ php --ri curl curl cURL support => enabled cURL Information => 8.19.0 Age => 11 Features AsynchDNS => Yes IPv6 => Yes SSL => Yes HTTP2 => Yes HTTP3 => Yes Directive => Local Value => Master Value curl.cainfo => no value => no value
If the target module is not loaded, PHP prints Extension 'imagick' not present. instead of the configuration block. Exact feature flags and linked library versions vary by build.
$ php --ini Configuration File (php.ini) Path: "/usr/local/etc/php/8.5" Loaded Configuration File: "/usr/local/etc/php/8.5/php.ini" Scan for additional .ini files in: "/usr/local/etc/php/8.5/conf.d" Additional .ini files parsed: (none)
The reported main file and scan directory show where extension= and zend_extension= directives come from for the current CLI binary. Exact paths vary by package source and runtime.
Related: How to find PHP configuration files
$ php -r 'printf("SAPI=%s\ncurl=%s\n", PHP_SAPI, extension_loaded("curl") ? "loaded" : "not loaded");'
SAPI=cli
curl=loaded
The extension name passed to extension_loaded() is case-insensitive, but the result still applies only to the SAPI that executed the code.