skip to content

INI Directives & Extensions

A setting can come from php.ini, a conf.d scan file, a .user.ini or ini_set(), and extensions are loaded the same way. Interviewers probe where a value comes from and who may change it.

part ofPHPoverview, primer and where to startread it →
on this pageshow

explore

questions

5

In PHP, how do you find which php.ini file is actually loaded, and why might editing php.ini seem to change nothing?

level: juniorimportance: must knowfreq 58%

answer

  1. php --ini for the CLI
  2. php_ini_loaded_file() from a web page
  3. CLI and FPM may load different files
  4. read once at startup, so restart
  5. (none) means built-in defaults

basics

~20 s

Run 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 lines
bash
php --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.ini

go deeper

for a junior

Know php --ini and phpinfo(), and that PHP-FPM or Apache must be restarted to pick up php.ini changes.

for a middle

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.

for a senior

Make the loaded configuration part of deployment review: confirm the production template is loaded by the web SAPI and that nothing later overrides it.

for a principal

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.
open as a page

On a PHP photo-contest site on a shared host, why does ini_set('upload_max_filesize', '20M') fail to raise the upload limit?

level: middleimportance: must knowfreq 52%

basics

~20 s

upload_max_filesize is changeable only at INI_PERDIR or INI_SYSTEM level, so ini_set() from a script refuses it and returns false. The upload is also parsed before the script runs. Set it in php.ini, .user.ini or .htaccess instead.

open as a page

In PHP, how are extra .ini files in a conf.d scan directory loaded, and when do you use zend_extension= instead of extension=?

level: middleimportance: should knowfreq 32%

basics

~20 s

After php.ini, PHP parses every .ini file in the scan directory in alphabetical order; PHP_INI_SCAN_DIR overrides that directory. extension= loads a regular extension, while zend_extension= loads one that hooks the Zend engine itself, such as Xdebug.

open as a page

In PHP, how do .user.ini files work, which SAPIs read them, and why can a change take minutes to appear?

level: middleimportance: should knowfreq 34%

basics

~20 s

.user.ini files are per-directory ini files read only by the CGI and FastCGI SAPIs, PHP-FPM included. PHP scans from the script's directory up to the document root and caches them for user_ini.cache_ttl, 300 seconds by default.

open as a page

How do PHP's disable_functions and open_basedir directives harden a server, and why is neither a real security boundary on its own?

level: seniorimportance: should knowfreq 30%

basics

~20 s

disable_functions removes named internal functions and open_basedir limits which paths PHP's file functions may open. Both are useful defence in depth, but the manual says disable_functions can be circumvented, and open_basedir does not bind child processes.

open as a page