In PHP, how do you find which php.ini file is actually loaded, and why might editing php.ini seem to change nothing?
answer
- php --ini for the CLI
- php_ini_loaded_file() from a web page
- CLI and FPM may load different files
- read once at startup, so restart
- (none) means built-in defaults
basics
~20 sRun php --ini for the CLI, or call php_ini_loaded_file() or phpinfo() from a web page, since each SAPI may load a different file. php.ini is read at startup, so PHP-FPM or Apache must be restarted after an edit.
solid answer
~40 s`php --ini` prints the CLI's configuration: the directory searched, the **Loaded Configuration File** (or `(none)`), the scan directory and the additional `.ini` files parsed. But the CLI and the web SAPI are separate processes and often load **different** files, so to see what the web app uses, call `php_ini_loaded_file()` and `php_ini_scanned_files()` (both `string|false`) or `phpinfo()` from a page served by it. Edits appear to do nothing for three usual reasons: you edited the file another SAPI loads; PHP-FPM or Apache's module read php.ini **once at startup** and must be reloaded; or a later file, such as one in the scan directory or a per-directory override, sets the same directive again. If no file loads at all, PHP runs on built-in defaults, which are not the production-safe values shipped in `php.ini-production`.
code
bash · 5 linesphp --ini
# Configuration File (php.ini) Path: "/usr/local/etc/php"
# Loaded Configuration File: "/usr/local/etc/php/php.ini"
# Scan for additional .ini files in: "/usr/local/etc/php/conf.d"
# Additional .ini files parsed: /usr/local/etc/php/conf.d/20-intl.inigo deeper
Know php --ini and phpinfo(), and that PHP-FPM or Apache must be restarted to pick up php.ini changes.
Explain that each SAPI may load its own file, how scan directories and per-directory overrides layer on top, and how master and local values differ.
Make the loaded configuration part of deployment review: confirm the production template is loaded by the web SAPI and that nothing later overrides it.
Standardise configuration across a fleet so every SAPI's effective settings are known, versioned and reviewable rather than drifting per server.
## Where configuration comes from PHP reads its main configuration file, **php.ini**, when the process starts. The manual lists the search order: a SAPI-specific location (for example the `-c` option of the CLI), the `PHPRC` environment variable, the current directory for non-CLI SAPIs, then the compile-time default path. If a file named `php-SAPI.ini` exists, such as `php-cli.ini`, it is used **instead of** `php.ini` for that SAPI. After the main file, PHP parses every `.ini` file in the **scan directory**. The result: one server can have several SAPIs, each with its own loaded files. ## Finding the loaded files | Tool | Shows | Which SAPI | |---|---|---| | `php --ini` | search path, loaded file, scan dir, extra files | the CLI only | | `php_ini_loaded_file()` | path of the main file, or `false` | whichever SAPI runs the call | | `php_ini_scanned_files()` | comma-separated extra files, or `false` | whichever SAPI runs the call | | `phpinfo()` | everything, including each directive's local and master value | whichever SAPI runs the call | | `ini_get('memory_limit')` | the current value of one directive, as a string | whichever SAPI runs the call | The key habit: **ask the SAPI you care about**. `php --ini` on a web server tells you about cron jobs and Composer, not about the pages PHP-FPM serves. ## Why an edit seems to do nothing 1. **Wrong file.** The web SAPI loads a different php.ini from the one you edited. Check `php_ini_loaded_file()` from a web page. 2. **No restart.** The manual notes that server-module SAPIs read php.ini only once when the server starts; CGI and CLI read it on every invocation. PHP-FPM also reads it at startup, so it needs a reload. 3. **Overridden later.** A file in the scan directory, a `.user.ini` or `.htaccess` in the app's directory, or an `ini_set()` call in code sets the same directive again. `phpinfo()` shows both the **master value** (from the configuration files) and the **local value** (after per-directory and runtime changes). 4. **Typo or wrong section.** An unknown directive name is silently ignored in php.ini, so a misspelling looks exactly like no change. ## No php.ini at all When `php --ini` reports `Loaded Configuration File: (none)`, PHP runs on its **built-in defaults**. Those are not tuned for production. The header of `php.ini-production` lists where the shipped files differ from the defaults, for example: | Directive | Built-in default | php.ini-development | php.ini-production | |---|---|---|---| | `display_errors` | On | On | Off | | `log_errors` | Off | On | On | | `zend.exception_ignore_args` | Off | Off | On | | `zend.assertions` | 1 | 1 | -1 | | `output_buffering` | Off | 4096 | 4096 | ## A step-by-step check When a setting seems wrong on a live site, work through it in order: 1. From a page served by the site, print `PHP_SAPI`, `php_ini_loaded_file()` and `php_ini_scanned_files()`. 2. Open those exact files and find the directive; remember a later scan file wins over php.ini. 3. Compare `ini_get()` with the master value in `phpinfo()`: if they differ, a per-directory file or `ini_set()` changed it. 4. After fixing the file, reload PHP-FPM or the web server so the processes read it again. 5. Re-run step 1 to confirm, and remove the diagnostic page. ## Production versus development files PHP ships two templates, **`php.ini-development`** and **`php.ini-production`**. Neither is loaded automatically; an installer or you copy one to the loaded location. - The **development** file favours visibility: errors on screen, assertions active. - The **production** file favours safety and speed: errors logged rather than shown, exception arguments left out of stack traces, assertion code not even compiled. A common incident is a server that has **no** php.ini, or a copy of the development file, in production, which shows errors and file paths to visitors. Checking the loaded file is part of any deployment review. The production file is a starting point, not a finished configuration: limits such as `memory_limit` or upload sizes still need values that fit the application, set in php.ini or a scan-directory file that is kept under version control.
- Why does php --ini on the server disagree with phpinfo() in the browser?php --ini describes the CLI SAPI, while phpinfo() in the browser describes the web SAPI, usually PHP-FPM or Apache's module. They start separately and can load different php.ini files and scan directories, so each must be asked about itself.
- What happens if no php.ini is found at all?PHP starts with its built-in defaults, and php --ini reports the loaded file as (none). Those defaults are not production-safe: display_errors is on and log_errors is off, among others, so a production server should always load a reviewed file.
- Do you need to restart PHP-FPM after editing php.ini?Yes. FPM reads php.ini when its processes start, so edits take effect after a reload or restart. The CLI and CGI read it on every invocation, which is why a quick test from the shell can show the new value while the site does not.
Like a thermostat with a schedule stored in two places: changing the copy in the drawer does nothing, and even the right copy only takes effect after the unit reboots and reads it again.
saying these in an interview costs you the question
- php --ini shows the configuration the web server uses.
- Editing php.ini takes effect on the next request under PHP-FPM.
- Every PHP process on a server loads the same php.ini.
- Without a php.ini, PHP uses the production-safe values by default.
- A misspelled directive in php.ini triggers a startup error.