A PHP file does not fully describe how it will run. The server API that starts it, and the configuration in force, decide which files count as PHP, whether certain tags work and what happens to errors. This page covers only the settings that bear on how a file is read and run.
Server APIs
A SAPI connects the PHP engine to whatever starts it.
php_sapi_name() and the constant PHP_SAPI give its name.
| Name | Runs under |
|---|---|
cli | The command line: php script.php |
cli-server | The built-in development web server: php -S localhost:8000 |
fpm-fcgi | PHP-FPM, the FastCGI process manager. The usual choice behind nginx, and recommended with Apache |
cgi-fcgi | Plain CGI or FastCGI |
apache2handler | mod_php, PHP as an Apache module |
litespeed | LiteSpeed |
embed | PHP embedded in another program |
phpdbg | The phpdbg debugger |
Under a web SAPI each request normally runs a script from a clean state: variables, objects and included code are gone when the request ends.
How a web server picks PHP files
The file extension means nothing to PHP. It is the web server’s configuration that sends some names to PHP, and every other file is served as it is.
<FilesMatch \.php$>
SetHandler application/x-httpd-php
</FilesMatch>
<FilesMatch "\.phps$">
SetHandler application/x-httpd-php-source
</FilesMatch>
mod_php. Other extensions such as .phtml are enabled by matching them toolocation ~* \.php$ {
fastcgi_index index.php;
fastcgi_pass 127.0.0.1:9000;
include fastcgi_params;
fastcgi_param SCRIPT_FILENAME $document_root$fastcgi_script_name;
}
.php requests to PHP-FPM- Use a pattern anchored to the end of the name. A looser rule, such as
AddType, can make a name likeexploit.php.jpgrun as PHP. - The
.phpshandler sends highlighted source to the browser. It should not be enabled on production systems. - The manual advises setting
cgi.fix_pathinfo=0so that PHP does not run a different file from the one requested. PHP-FPM must never be reachable from an untrusted network, because a FastCGI client controls settings such asauto_prepend_file. - A file without a handler is sent as plain text, so its source reaches the browser. Keep code outside the document root where possible.
The command line
The CLI reads the file named on the command line, or standard input. The shebang line of the script is skipped. It starts in quiet mode, with no HTTP headers, and does not change the working directory to the script’s directory.
| Option | Purpose |
|---|---|
-f file | Run a file. The flag is optional |
-r code | Run code given on the command line, without tags |
-l | Check syntax only. Exits non-zero on failure |
-s | Output the source as highlighted HTML |
-a | Interactive shell |
-S addr:port, -t dir | The built-in development server and its document root. It is not for production |
-d name=value | Set a directive for this run |
-c path, -n | Use a specific php.ini, or none |
-v, -i | Version, and full configuration |
The CLI overrides some settings so that scripts work well in a terminal. These cannot
be set in php.ini, but can be changed by ini_set() at run
time.
| Directive | CLI value |
|---|---|
html_errors | Off |
implicit_flush | On |
max_execution_time | 0, unlimited |
output_buffering | Off, though the output functions remain available |
The constants STDIN, STDOUT and STDERR are
open stream handles, available on the CLI only. $argc and
$argv are always set on the CLI. Under a web SAPI the
register_argc_argv setting can derive them from the query string, which
is deprecated since PHP 8.5, so do not test for the CLI by looking for them.
Test PHP_SAPI.
Settings that change how a file runs
The defaults below are the ones built in to PHP. The php.ini-production
file shipped with PHP changes several of them
(manual: list of directives).
| Directive | Default | Effect on a file |
|---|---|---|
short_open_tag | On | Whether <? opens PHP mode |
auto_prepend_file | None | A file run before the main script, as if by require |
auto_append_file | None | A file run after the main script. Not run if the script calls exit() |
include_path | Includes . | Directories searched by include. Entries are separated by : on Unix and ; on Windows |
open_basedir | None | Limits the files PHP may open, including includes |
allow_url_include | Off | Whether a URL can be included. Deprecated since 7.4 |
allow_url_fopen | On | Whether file functions can open URLs |
engine | On | Turns PHP on or off for a host or directory in Apache |
default_charset | UTF-8 | The charset in the default Content-Type header, and the default for functions such as htmlspecialchars() |
output_buffering | Off | Holds output back, which allows headers to be sent later |
error_reporting | E_ALL (since 8.0) | Which levels are reported |
display_errors | On | Prints errors into the output. Should be off in production |
log_errors | Off | Logs errors to the error_log destination |
precision | 14 | Significant digits shown when a float becomes a string |
serialize_precision | -1 | Digits used by var_export(), json_encode() and serialize(). -1 means the shortest form that round-trips |
zend.assertions | 1 | assert(): 1 runs them, 0 skips them, and -1 compiles them away entirely |
variables_order | EGPCS | Which superglobals are filled |
disable_functions | None | Names of functions that cannot be called. Set only in php.ini |
memory_limit | 128M | The most memory a script may allocate |
max_execution_time | 30 | Seconds a script may run, not counting system calls |
Source encoding
Only source in an encoding that is not ISO-8859-1 compatible needs these. UTF-8 does not.
| Directive | Default | Meaning |
|---|---|---|
zend.multibyte | Off | Turns on parsing of multi-byte source such as Shift-JIS or Big5. Requires mbstring |
zend.script_encoding | None | The default source encoding, used unless the script starts with a declare(encoding=…) |
Where settings live
Settings are read from php.ini and extra files in a scan directory.
Each directive has a mode saying where it can be changed.
| Mode | Can be set in |
|---|---|
INI_USER | Scripts with ini_set(), the Windows registry and .user.ini |
INI_PERDIR | php.ini, .htaccess, httpd.conf and .user.ini |
INI_SYSTEM | php.ini and httpd.conf only |
INI_ALL | Anywhere |
.user.ini files are read only under the CGI and FastCGI SAPIs, from the
script’s directory up to the document root. .htaccess files are the
equivalent under mod_php. short_open_tag is
INI_PERDIR, so ini_set() cannot change it.
OPcache
PHP compiles each file to bytecode (opcodes) before running it. The OPcache extension keeps that bytecode in shared memory, so that a file is not recompiled on each request. Since PHP 8.5 it is a non-optional part of PHP. There is no standard compiled file format: PHP normally distributes source, not bytecode.
| Directive | Default | Meaning |
|---|---|---|
opcache.enable | 1 | Turns the cache on |
opcache.enable_cli | 0 | Turns it on for the CLI |
opcache.validate_timestamps | 1 | Checks whether files changed. With it off, a changed file is not picked up until the cache is reset |
opcache.revalidate_freq | 2 | How many seconds between checks. So a saved file may take effect up to two seconds later |
opcache.preload | None | A script compiled at server start (PHP 7.4). Not supported on Windows |