PHP Configuration (php.ini)
PHP Configuration (php.ini) What Is php.ini? In simple terms: php.ini is PHP's settings file. It controls how much memory a script may use, how long it may run, how large uploads can be, whether error
PHP Configuration (php.ini)
What Is php.ini?
In simple terms: php.ini is PHP's settings file. It controls how much memory a script may use, how long it may run, how large uploads can be, whether errors are shown, which time zone is used, and hundreds of other behaviors. The same PHP code can behave very differently depending on these settings, so knowing where they live and how to change them is an essential deployment skill.
Technically: When PHP starts, it reads a main php.ini file and, typically, additional .ini files from a scan directory (for example, conf.d/). Each SAPI — the command line (CLI), PHP-FPM, the Apache module — can have its own configuration. Settings (called directives) can be changed at different levels depending on their changeable mode: some only in php.ini, others per directory (.user.ini, web server configuration) or at runtime with ini_set().
Finding the Active Configuration
php --ini
Configuration File (php.ini) Path: /etc/php/8.4/cli
Loaded Configuration File: /etc/php/8.4/cli/php.ini
Scan for additional .ini files in: /etc/php/8.4/cli/conf.d
Additional .ini files parsed: /etc/php/8.4/cli/conf.d/10-opcache.ini,
/etc/php/8.4/cli/conf.d/20-mysqlnd.ini, ...
This shows the CLI configuration. The web server's PHP-FPM uses a different file — on Debian/Ubuntu, /etc/php/8.4/fpm/php.ini. To see the configuration the web uses, check it from a web request (a protected admin page calling php_ini_loaded_file()), or run php-fpm8.4 -i | grep "Loaded Configuration".
PHP's source distribution includes two templates: php.ini-development (show errors, helpful for debugging) and php.ini-production (secure defaults). Production servers should be based on the production template.
php.ini Syntax
; Lines starting with a semicolon are comments
memory_limit = 256M ; sizes use K, M, G
max_execution_time = 30 ; seconds
display_errors = Off ; booleans: On/Off, 1/0, true/false, yes/no
date.timezone = "Asia/Kolkata"
error_log = /var/log/php/app-error.log
[opcache] ; sections are for readability (and some special cases)
opcache.enable = 1
After changing php.ini, restart the PHP process that uses it (for example, sudo systemctl restart php8.4-fpm), because PHP-FPM reads configuration only at startup. The CLI reads it every time a script starts.
Important Directives
Resources and Limits
| Directive | Typical Value | Purpose |
|---|---|---|
memory_limit | 128M–512M | Maximum memory per script (-1 = unlimited, only sensible in the CLI) |
max_execution_time | 30 | Maximum script runtime in seconds for web requests (the CLI default is 0, unlimited) |
max_input_time | 60 | Maximum time for parsing request data |
max_input_vars | 1000 | Maximum number of input variables (protects against hash-collision attacks) |
upload_max_filesize | 10M | Maximum size of one uploaded file |
post_max_size | 12M | Maximum size of the whole request body (must exceed upload_max_filesize) |
max_file_uploads | 20 | Maximum files per request |
Errors and Security
| Directive | Production Value | See |
|---|---|---|
display_errors | Off | Error Reporting in Production |
log_errors / error_log | On / log file path | Error Logging |
error_reporting | E_ALL | Error Handling |
expose_php | Off | Hiding PHP |
allow_url_include | Off | Filesystem Security |
open_basedir, disable_functions | As needed | Filesystem Security |
session.* (cookie_secure, cookie_httponly, use_strict_mode, …) | Hardened | Session Security |
Locale and Performance
| Directive | Purpose |
|---|---|
date.timezone | Default time zone (see Timezones) |
default_charset | UTF-8 (the default) |
opcache.* | Bytecode caching — essential for production speed (see OPcache & Performance) |
realpath_cache_size, realpath_cache_ttl | Caching of resolved file paths, helpful for large applications |
Reading and Changing Settings at Runtime
<?php
echo "memory_limit: " . ini_get('memory_limit') . "\n";
echo "max_execution_time: " . ini_get('max_execution_time') . "\n";
$old = ini_set('max_execution_time', '60');
var_dump($old);
echo "max_execution_time now: " . ini_get('max_execution_time') . "\n";
var_dump(ini_set('expose_php', '0'));
Output (command line)
memory_limit: 128M
max_execution_time: 0
string(1) "0"
max_execution_time now: 60
bool(false)
How It Works
ini_get()returns a setting's current value as a string — exactly as configured (128M, not a number of bytes).ini_set()changes a setting for the current script only and returns the previous value.expose_phpcannot be changed at runtime, soini_set()returnsfalse.
Changeable Modes
| Mode | Where the Directive Can Be Set | Examples |
|---|---|---|
PHP_INI_ALL | Anywhere, including ini_set() | memory_limit, max_execution_time, display_errors, date.timezone |
PHP_INI_PERDIR | php.ini, .user.ini, web server config — not ini_set() | upload_max_filesize, post_max_size, short_open_tag |
PHP_INI_SYSTEM | php.ini or the server configuration only | expose_php, disable_functions, opcache.memory_consumption |
upload_max_filesize and post_max_size are evaluated before your script runs (while PHP reads the request), which is why changing them with ini_set() is impossible.
Converting Size Values
Values such as 256M must be converted before numeric comparisons:
<?php
function iniBytes(string $value): int
{
$value = trim($value);
$number = (int) $value;
return match (strtoupper(substr($value, -1))) {
'G' => $number * 1024 ** 3,
'M' => $number * 1024 ** 2,
'K' => $number * 1024,
default => $number,
};
}
echo iniBytes('256M') . "\n";
echo iniBytes('2G') . "\n";
Output
268435456
2147483648
PHP 8.2 added ini_parse_quantity(), which performs this conversion natively: ini_parse_quantity('256M') returns 268435456.
Per-Directory and Per-Pool Configuration
| Method | Applies To | Example |
|---|---|---|
.user.ini in a directory | PHP-FPM/CGI requests for scripts in that directory tree | upload_max_filesize = 20M |
| PHP-FPM pool configuration | All requests handled by a pool | php_admin_value[memory_limit] = 256M |
Apache (mod_php) | Directories/virtual hosts | php_value memory_limit 256M |
php_admin_value in an FPM pool cannot be overridden by .user.ini or ini_set() — useful for enforcing limits on shared servers. .user.ini files are re-read periodically (user_ini.cache_ttl, 300 seconds by default).
Common Mistakes
Editing the Wrong php.ini
Effect: Changes to the CLI's file do not affect the website (or vice versa).
Fix: Check the loaded file for each SAPI; restart PHP-FPM after changes.
post_max_size Smaller Than upload_max_filesize
Effect: Large uploads fail with empty $_POST and $_FILES.
Fix: Keep post_max_size larger than the maximum upload size plus form data.
Using ini_set() for Directives It Cannot Change
Effect: The change silently fails (false is returned).
Fix: Check the directive's changeable mode; set it in php.ini or the server configuration.
Unlimited Resources in Web Requests
Effect: Runaway scripts exhaust server memory or workers.
Fix: Keep memory_limit and max_execution_time bounded for web requests; raise them only for specific CLI jobs.
Best Practices
- Base production configuration on
php.ini-productionand keep it under version control (or configuration management). - Know which
php.inieach SAPI loads, and restart PHP-FPM after changes. - Set limits deliberately: memory, execution time, uploads, and input variables.
- Use
ini_set()only forPHP_INI_ALLdirectives that genuinely vary per script. - Enforce critical settings with
php_admin_valuein FPM pools on shared servers.
Official reference: https://www.php.net/manual/en/configuration.php