PHP is a popular general-purpose scripting language that is especially suited to web development. This guide covers the php-src repository — the official C source code of the PHP interpreter itself. It is written for people who build PHP from source, run the bundled command-line tools (php, php-cgi, php-fpm, phpdbg), and configure a PHP runtime via php.ini.
Note
This guide documents the interpreter source tree, not the PHP language. For the PHP language manual (functions, syntax, classes), see php.net/docs. Here you will learn how to compile PHP, what the binaries do, and how to configure the runtime they produce.
This source tree builds PHP 8.6 (the master development branch). Everything below is derived directly from the source at commit 95b5b487.
Table of Contents
- Quick Start
- What You Are Building
- Requirements
- Building PHP From Source
- Running the PHP CLI (
php) - The Built-in Web Server
- The Other SAPIs (
php-cgi,php-fpm,phpdbg) - Configuring PHP with
php.ini - Extensions
- Common Tasks
- Running the Test Suite
- Troubleshooting
- FAQ
- Reference
1. Quick Start
The fastest path from a fresh Git clone to a working php binary on a Debian/Ubuntu machine:
# 1. Install build prerequisites
sudo apt install -y pkg-config build-essential autoconf bison re2c \
libxml2-dev libsqlite3-dev
# 2. Clone the source
git clone https://github.com/php/php-src.git
cd php-src
# 3. Generate the configure script
./buildconf
# 4. Configure the build (production defaults)
./configure
# 5. Compile (use all CPU cores)
make -j"$(nproc)"
# 6. Run the freshly built interpreter
sapi/cli/php -v
Expected output from the final command:
PHP 8.6.0-dev (cli) (built: ... ) (NTS)
Copyright (c) The PHP Group
Zend Engine v4.6.0-dev, Copyright (c) Zend Technologies
Tip
You do not need to
make installto use the binary. After a build, the CLI lives atsapi/cli/phpinside the source tree and runs in place — ideal for testing changes.
Note
On a minimal Git build you need
autoconf,bison, andre2c. A default build additionally needslibxml2andlibsqlite3. See Requirements for other platforms.
2. What You Are Building
The php-src tree compiles into several executables, each called a SAPI (Server Application Programming Interface — the layer that connects the PHP engine to a host environment). When you run ./configure && make, you get a different set of binaries depending on which SAPIs you enabled.
| Binary | SAPI | What it is for | Built by default |
|---|---|---|---|
php |
cli |
Command-line interpreter, scripts, REPL, built-in web server | Yes |
php-cgi |
cgi |
CGI/FastCGI executable for traditional web servers | Yes |
php-fpm |
fpm |
FastCGI Process Manager — the production web runtime | Opt-in (--enable-fpm) |
phpdbg |
phpdbg |
Interactive step debugger for PHP scripts | Opt-in (--enable-phpdbg) |
libphp.so |
apache2handler |
Apache module (mod_php) |
Opt-in (--with-apxs2) |
libphp.so/.a |
embed |
Embed PHP into a C/C++ application | Opt-in (--enable-embed) |
| — | litespeed |
LiteSpeed web server LSAPI binary | Opt-in (--enable-litespeed) |
Internally, every SAPI sits on top of two shared layers:
┌───────────────────────────────────────────────────────────┐
│ SAPI binaries: php php-cgi php-fpm phpdbg mod_php │
├───────────────────────────────────────────────────────────┤
│ Bundled extensions (ext/): standard, pdo, mbstring, ... │
├───────────────────────────────────────────────────────────┤
│ PHP core (main/): startup, php.ini, streams, SAPI glue │
├───────────────────────────────────────────────────────────┤
│ Zend Engine (Zend/): lexer → compiler → opcodes → VM │
└───────────────────────────────────────────────────────────┘
Note
The deep architecture (how the Zend Engine compiles and executes code, the memory manager, OPcache, the JIT) is covered in the Admin Guide. This User Guide focuses on building and using the binaries.
3. Requirements
Build toolchain
| Tool | Why it is needed | Minimal build | Default build |
|---|---|---|---|
C compiler (gcc/clang) |
Compiles the C sources | Required | Required |
make |
Drives the build | Required | Required |
autoconf |
Generates configure via ./buildconf |
Required | Required |
bison |
Generates the PHP language parser | Required | Required |
re2c |
Generates the lexer/scanner | Required | Required |
pkg-config |
Locates system libraries | Recommended | Recommended |
libxml2 |
Required by several core extensions | — | Required |
libsqlite3 |
Default SQLite/PDO support | — | Required |
Install prerequisites by platform
Ubuntu / Debian
sudo apt install -y pkg-config build-essential autoconf bison re2c \
libxml2-dev libsqlite3-dev
Fedora
sudo dnf install re2c bison autoconf make ccache libxml2-devel sqlite-devel
macOS (Homebrew)
brew install autoconf bison re2c libiconv libxml2 sqlite
macOS (MacPorts)
sudo port install autoconf bison re2c libiconv libxml2 sqlite3
Important
On macOS, the system
bisonis usually too old. Homebrew/MacPorts install a newerbisonthat is not on the defaultPATH. Add it before running./buildconf(Homebrew prints the exactexport PATH=...line after install).
Prebuilt binaries (skip building entirely)
If you only want to run PHP, you do not need this repository:
- Windows: download
*.exebuilds from windows.php.net and run them directly after extracting. - Linux/macOS: use your distribution's package manager or see the installation chapter at php.net.
Tip
Build from source when you are developing PHP itself, need a custom extension set, want the JIT/debug build, or are running an architecture without prebuilt binaries.
4. Building PHP From Source
The build is a standard Autotools flow: buildconf → configure → make → (optionally) make install.
Step 1 — Generate configure
./buildconf
This runs autoconf to produce the configure script from configure.ac and the per-extension config.m4 files.
Note
On a release tarball from php.net,
configurealready exists and you can skip./buildconf. On a Git checkout you must run it. Use./buildconf --forceifconfigureis stale after pulling changes.
Step 2 — Configure the build
# For development (assertions, debug symbols, no optimization surprises)
./configure --enable-debug
# For production
./configure
See every available switch with:
./configure --help
The configure step decides which SAPIs and extensions are compiled in. A few of the most common switches:
| Switch | Effect |
|---|---|
--enable-debug |
Debug build: assertions on, symbols, leak checks. Recommended for development. |
--enable-fpm |
Build the php-fpm FastCGI process manager. |
--enable-phpdbg |
Build the phpdbg interactive debugger. |
--enable-embed |
Build the embed SAPI (libphp) to embed PHP in C/C++. |
--with-apxs2[=FILE] |
Build the Apache 2 module (mod_php). |
--enable-opcache-jit |
Enable JIT support in OPcache (on by default when OPcache builds). |
--disable-all |
Start from a minimal build and add only what you --enable/--with. |
--with-config-file-path=PATH |
Compile in the directory PHP searches for php.ini. |
--with-config-file-scan-dir=PATH |
Compile in an extra directory of *.ini fragments. |
--prefix=PATH |
Installation prefix (default /usr/local). |
Tip
For a lean, fast build while hacking on the engine, use
./configure --disable-all --enable-debug. It skips the dozens of optional extensions and compiles in a fraction of the time.
A fuller list of extension and feature switches is in the Reference.
Step 3 — Compile
make -j"$(nproc)"
The -j flag sets the number of parallel jobs; matching it to your core count (nproc) is the usual choice.
Warning
A full default build compiles thousands of C files and can take several minutes even on a fast machine. Install
ccache(Fedora command above includes it) to make rebuilds dramatically faster.
Step 4 — Install (optional)
make install
make install copies the binaries, headers, and the php man pages into your --prefix. Depending on the prefix and your permissions it may require sudo.
Note
If you only want to run the interpreter in place for testing, skip
make installand callsapi/cli/phpdirectly from the build tree.
Verifying the build
sapi/cli/php --version
sapi/cli/php -m # list compiled-in modules/extensions
sapi/cli/php -i | head # full configuration dump (phpinfo)
5. Running the PHP CLI (php)
The cli SAPI is the workhorse: it runs scripts, evaluates inline code, lints files, starts a development web server, and provides an interactive shell. All forms accept the options listed in the CLI reference.
Usage forms
php [options] [-f] <file> [--] [args...]
php [options] -r <code> [--] [args...]
php [options] [-B <begin_code>] -R <code> [-E <end_code>] [--] [args...]
php [options] [-B <begin_code>] -F <file> [-E <end_code>] [--] [args...]
php [options] -S <addr>:<port> [-t docroot] [router]
php [options] -- [args...]
php [options] -a
Run a script file
php script.php
php -f script.php # explicit form, identical effect
php script.php arg1 arg2 # pass arguments (available in $argv)
Tip
Use
--to separate PHP options from script arguments when an argument starts with-:php script.php -- --verbose --name=foo
Run inline code with -r
php -r 'echo PHP_VERSION, PHP_EOL;'
8.6.0-dev
Note
With
-ryou write PHP without the<?php ?>tags.
Lint (syntax-check) a file with -l
php -l script.php
No syntax errors detected in script.php
This parses the file and reports syntax errors without executing it — handy in CI and pre-commit hooks.
Process input line-by-line (-R / -F)
The -B/-R/-E trio runs code before, for each input line, and after STDIN — an awk-like mode. $argn holds the current line; $argi the line number.
# Count non-empty lines from stdin
cat file.txt | php -B '$c=0;' -R 'if(trim($argn)!=="") $c++;' -E 'echo "$c\n";'
Use -F <file> instead of -R <code> to run a whole script per input line.
Interactive shell (-a)
php -a
Interactive shell
php >
Important
The interactive shell (
-a) requires PHP to be built with the readline extension (--with-readlineor--with-libedit). Without it,-afalls back to a much more limited line-buffered mode.
Inspect the runtime
php -i # full phpinfo() text dump
php -m # list loaded modules (extensions)
php --ini # show which php.ini files are loaded
php --ini=diff # show only INI values that differ from built-in defaults
Reflection helpers
PHP can print structured information about functions, classes, and extensions straight from the CLI:
php --rf str_replace # reflect a function's signature
php --rc DateTime # reflect a class
php --re json # reflect an extension (its functions/classes/ini)
php --ri opcache # show an extension's runtime configuration
php --rz <name> # reflect a Zend extension
Tip
php --ri opcacheis the quickest way to confirm whether OPcache (and the JIT) is active and how it is configured, without writing a script.
Override configuration per invocation
php -d memory_limit=512M -d display_errors=1 script.php # set INI entries inline
php -c /path/to/custom.ini script.php # use a specific php.ini
php -n script.php # ignore all php.ini files
Note
-d key=valuecan be repeated. These overrides apply only to that single invocation, layered on top of the loadedphp.ini.
6. The Built-in Web Server
The CLI ships a small web server intended for local development and testing — never for production.
Start the server
php -S localhost:8000
[..] PHP 8.6.0-dev Development Server (http://localhost:8000) started
Serve files from a specific document root:
php -S localhost:8000 -t public/
Use a router script
A router script lets a single front controller handle every request (the pattern most frameworks use):
php -S localhost:8000 router.php
Inside router.php, return false to let the server serve a real static file as-is:
<?php
if (preg_match('#\.(?:png|jpg|css|js)$#', $_SERVER["REQUEST_URI"])) {
return false; // serve the requested file directly
}
require __DIR__ . '/index.php'; // otherwise route through the app
Warning
The built-in server is single-threaded by default and has no security hardening. It is a development convenience only. For production, use
php-fpmbehind nginx/Apache, ormod_php— see the Admin Guide.
Tip
Colorized CLI server output is controlled by the
cli_server.colorINI directive (Onin the production template). Bind to0.0.0.0:8000to accept connections from other machines on your network — only do this on trusted networks.
7. The Other SAPIs (php-cgi, php-fpm, phpdbg)
php-cgi — CGI / FastCGI executable
php-cgi is the CGI binary, used by web servers that speak CGI or FastCGI directly. It shares most options with the CLI plus a few CGI-specific ones:
php-cgi -b 127.0.0.1:9000 # run as a FastCGI server bound to host:port
php-cgi -T 10 script.php # measure execution time, repeating 10 times
| Option | Meaning |
|---|---|
-b <address:port>|<port> |
Bind path/address for an external FastCGI server. |
-T <count> |
Measure execution time, repeating the request count times. |
-q |
Quiet mode: do not generate HTTP headers. |
Note
For new deployments prefer
php-fpmoverphp-cgi. FPM is a purpose-built process manager with pooling, status reporting, and graceful reloads.
php-fpm — FastCGI Process Manager
php-fpm is the production runtime that nginx and Apache talk to over FastCGI. It is configured through php-fpm.conf (global) and pool files in php-fpm.d/.
php-fpm -t # test (validate) the configuration and exit
php-fpm -F # run in the foreground (do not daemonize)
php-fpm -y /etc/php-fpm.conf # use a specific config file
php-fpm -p /run/php # set the prefix for relative paths
| Option | Meaning |
|---|---|
-t / --test |
Validate configuration; exit non-zero on error. Run this before every reload. |
-F / --nodaemonize |
Stay in the foreground (the right choice under systemd/Docker). |
-D / --daemonize |
Force daemonization. |
-y <file> / --fpm-config |
Path to the FPM config file. |
-p <prefix> / --prefix |
Prefix for relative paths in the config. |
-g <file> / --pid |
PID file path. |
-R / --allow-to-run-as-root |
Permit running the master as root (discouraged). |
-O / --force-stderr |
Force error output to stderr. |
Important
Always run
php-fpm -tafter editing a pool file. A syntax error caught at reload time can otherwise take your site down. Pool tuning (pm,pm.max_children, etc.) is covered in the Admin Guide.
phpdbg — interactive debugger
phpdbg is a gdb-style interactive debugger for PHP scripts, built with --enable-phpdbg.
phpdbg script.php
[Welcome to phpdbg, the interactive PHP debugger, v0.5.0]
To get help using phpdbg type "help" and press enter
[Please report bugs to <http://bugs.php.net/report.php>]
prompt>
Inside the prompt you can set breakpoints (break), step (step/next), continue (run/continue), and inspect state.
| Option | Meaning |
|---|---|
-r |
Run the script immediately on launch. |
-e |
Generate ext_stmt opcodes (finer-grained stepping). |
-E |
Step through eval()'d code. |
-i <file> |
Use a specific phpdbg init file. |
-I |
Ignore the init file. |
-p [<num>] |
Print/dump opcodes (disassemble). |
-S <name> |
Override the SAPI name. |
-z <ext> |
Load a Zend extension. |
Tip
phpdbg -p script.phpdisassembles a script to its opcodes — a quick way to see what the compiler produced without running anything.
8. Configuring PHP with php.ini
PHP reads its runtime configuration from an INI file. The repository ships two starting points:
| File | Use for |
|---|---|
php.ini-development |
Local development — verbose errors, more diagnostics. |
php.ini-production |
Servers — errors hidden from output, hardened defaults. |
Copy the one you want to PHP's config directory (revealed by php --ini):
cp php.ini-production /usr/local/lib/php.ini # path depends on --with-config-file-path
php --ini # confirm which file is now loaded
How configuration is layered
- Built-in defaults compiled into PHP.
- The main
php.ini(location set at build time, overridable with-c). - Extra
*.inifiles in the scan directory (--with-config-file-scan-dir). - Per-invocation
-d key=valueoverrides (CLI) orphp_value/php_admin_value(FPM pools).
php --ini=diff # see exactly which entries differ from the built-in defaults
Frequently changed directives
These values are taken verbatim from php.ini-production:
| Directive | Production default | Purpose |
|---|---|---|
memory_limit |
128M |
Max memory a single script may allocate. |
max_execution_time |
30 |
Max seconds a script may run (CLI is exempt). |
max_input_time |
60 |
Max seconds spent parsing request input. |
post_max_size |
8M |
Max size of a POST body. |
upload_max_filesize |
2M |
Max size of a single uploaded file. |
max_file_uploads |
20 |
Max number of files per request. |
display_errors |
Off |
Whether errors print to output (keep Off in production). |
display_startup_errors |
Off |
Show errors during PHP startup. |
log_errors |
On |
Write errors to the error log. |
error_reporting |
E_ALL & ~E_DEPRECATED |
Which error levels are reported. |
expose_php |
On |
Send the X-Powered-By header (set Off to hide PHP). |
default_charset |
"UTF-8" |
Default charset for headers and output. |
allow_url_fopen |
On |
Allow URL wrappers in file functions. |
allow_url_include |
Off |
Allow include/require of URLs (keep Off). |
file_uploads |
On |
Enable HTTP file uploads. |
variables_order |
"GPCS" |
Which superglobals are populated and in what order. |
session.cookie_httponly |
1 |
Mark the session cookie HttpOnly. |
session.cookie_samesite |
"Lax" |
SameSite attribute for the session cookie. |
session.use_strict_mode |
1 |
Reject uninitialized session IDs. |
Caution
Keep
display_errors = Offandallow_url_include = Offon any server reachable from the internet. The first leaks internal paths and data; the second is a classic remote-code-execution vector.
Tip
Booleans accept
On/Off,1/0,true/false,yes/no. Sizes acceptK,M,Gsuffixes (e.g.512M).
A more complete directive table — including session, mail, and database-extension defaults — is in the Reference.
9. Extensions
Extensions add functionality on top of the engine. PHP ships with many bundled extensions and supports loading additional ones.
What ships in this tree
The ext/ directory contains the bundled extensions, including (among ~70 total):
bcmath bz2 calendar ctype curl date dba dom exif ffi fileinfo
filter ftp gd gettext gmp hash iconv intl json ldap mbstring
mysqli mysqlnd odbc opcache openssl pcntl pcre pdo pdo_mysql
pdo_pgsql pdo_sqlite pgsql phar posix random readline reflection
session shmop simplexml snmp soap sockets sodium spl sqlite3
standard tidy tokenizer uri xml xmlreader xmlwriter xsl zip zlib
Note
ext/standardandext/splare always present — they provide the core function library and standard data structures.pcre,date,hash,json, andrandomare likewise effectively always built in.
Choosing extensions at build time
You select extensions when you run ./configure:
./configure \
--enable-mbstring \
--with-curl \
--with-openssl \
--enable-sockets \
--with-zip
--enable-NAMEis used for extensions with no external library dependency.--with-NAME[=DIR]is used for extensions that link a system library (point it at a non-standard install with=DIR).--disable-allplus explicit--enable/--withflags gives you a precisely minimal binary.
php -m # confirm what actually got compiled in
Loading shared extensions at runtime
Extensions built as shared objects (.so/.dll) are loaded via php.ini:
extension=curl
extension=/full/path/to/custom.so
zend_extension=opcache ; Zend extensions (e.g. OPcache) use this directive
Important
OPcache is a Zend extension and must be loaded with
zend_extension=opcache, notextension=. Loading it the wrong way silently fails.
Adding a brand-new extension
The repository includes a skeleton generator for authoring a new extension:
php ext/ext_skel.php --ext my_extension
This scaffolds ext/my_extension/ with the boilerplate (config.m4, a stub .c, tests) so you can start from a buildable shell. Additional community extensions are distributed via PECL.
10. Common Tasks
Check your PHP version and build flags
php -v # version + Zend Engine version + thread-safety (NTS/ZTS)
php -i | grep -i 'Configure Command' # the exact ./configure line used
Find your loaded configuration files
php --ini
Configuration File (php.ini) Path: /usr/local/lib
Loaded Configuration File: /usr/local/lib/php.ini
Scan for additional .ini files in: /usr/local/lib/php.d
Additional .ini files parsed: /usr/local/lib/php.d/10-opcache.ini
Test a script's syntax across a project
find src -name '*.php' -print0 | xargs -0 -n1 php -l
Serve a project locally
php -S 127.0.0.1:8080 -t public/ public/index.php
Run a one-off snippet
php -r 'var_dump(json_decode(file_get_contents("php://stdin"), true));' < data.json
Confirm an extension is available
php -m | grep -i curl # is curl loaded?
php --ri curl # detailed curl configuration
Rebuild after pulling new source
git pull
./buildconf --force # regenerate configure if build files changed
./configure --enable-debug # re-run with your chosen flags
make -j"$(nproc)"
Tip
If a rebuild behaves strangely after a big
git pull, runmake clean(orgit clean -xfdto wipe all generated files) and rebuild from scratch.
11. Running the Test Suite
PHP ships an extensive .phpt test suite driven by run-tests.php. After a successful build:
make test
Run tests in parallel and target specific directories:
make TEST_PHP_ARGS=-j4 test # 4 concurrent workers
make TESTS=tests/lang/ test # only the language tests
make TESTS=ext/json test # only the json extension's tests
Note
Keep the number of jobs at or below your core count. Some extension test suites (mysqli, pgsql, ldap, snmp, …) need a running service and credentials supplied through environment variables — see each
ext/<name>/tests/README.md.
Testing with OPcache and the JIT
make test TESTS="-d opcache.jit_buffer_size=16M -d opcache.enable=1 \
-d opcache.enable_cli=1 -d opcache.jit=tracing --repeat 2 \
-j$(nproc) ext/opcache Zend"
opcache.jit_buffer_size=16Mallocates JIT memory (enabling the JIT in tests).--repeat 2re-runs each test — some JIT bugs only appear on the second request (first compiles the trace, second executes it).
Tip
When chasing crashes, configure with
--enable-debugand one of--enable-address-sanitizer(fast, needs rebuild) or run under valgrind via-m --show-meminTEST_PHP_ARGS(no rebuild, slower).
12. Troubleshooting
Error: configure: error: bison is not found
Cause: bison is missing or too old (common on macOS where the system version is ancient).
Solution: Install a recent bison (brew install bison / apt install bison) and put it on your PATH before ./buildconf.
Prevention: Always install the full prerequisite list for your platform from Requirements.
Error: Cannot find autoconf. Please check your autoconf installation
Cause: ./buildconf cannot find autoconf.
Solution: Install autoconf (apt install autoconf / brew install autoconf), then re-run ./buildconf.
Prevention: Install build prerequisites before cloning.
Error: configure: error: Package requirements (libxml-2.0) were not met
Cause: The default build needs libxml2 development headers.
Solution: Install libxml2-dev (Debian) / libxml2-devel (Fedora) / brew install libxml2. If pkg-config still cannot find it, export PKG_CONFIG_PATH to its .pc directory.
Prevention: Install libxml2 and libsqlite3 dev packages, or use --disable-libxml plus --without-sqlite3/--disable-dom if you truly do not need them.
Error: No input file specified. (under FPM/CGI)
Cause: The web server passed a SCRIPT_FILENAME that does not exist, or security.limit_extensions blocked it.
Solution: Verify the web server's fastcgi_param SCRIPT_FILENAME points to a real file; check the FPM pool's security.limit_extensions.
Prevention: Keep document-root and FastCGI parameters consistent between the web server and FPM.
Warning: opcache.memory_consumption cannot be changed when OPcache is already set up
Cause: On ZTS builds, certain OPcache settings are locked once OPcache has initialized (observed in issue #22216 on 8.5 ZTS).
Solution: Set opcache.memory_consumption in the main php.ini so it is applied at startup, not via a per-request override.
Prevention: Configure OPcache sizing statically in php.ini; do not try to change it with -d/ini_set() after startup.
php -a prints Interactive mode enabled but has no line editing
Cause: PHP was built without the readline extension.
Solution: Rebuild with --with-readline (GNU readline) or --with-libedit (BSD libedit).
Prevention: Include a readline library when you configure if you rely on the interactive shell.
FPM: active processes exceed pm.max_children
Cause: Reported in issue #14212 — the status page can transiently show more active processes than the configured maximum during scaling.
Solution: Monitor over time rather than reacting to a single status snapshot; ensure pm.max_children is sized for your memory budget.
Prevention: Size pm.max_children from available_RAM / avg_process_size (see the Admin Guide).
make fails after a git pull
Cause: Stale generated files (parser, lexer, or configure) no longer match the sources.
Solution: ./buildconf --force, re-run ./configure, then make. If it persists, make clean or git clean -xfd and rebuild.
Prevention: Re-run ./buildconf --force whenever build-system files change upstream.
Tests fail only with the JIT enabled
Cause: A JIT trace bug that surfaces on repeated execution.
Solution: Reproduce with --repeat 2 and opcache.protect_memory=1; build with --enable-debug and AddressSanitizer to pinpoint it; report it upstream.
Prevention: Run the JIT test command from Running the Test Suite before relying on a JIT build.
13. FAQ
Q: Is php-src the same as the PHP language documentation?
No. php-src is the C source code of the interpreter. The language/function manual lives at php.net/docs. This repo's own docs/ is internal documentation about the interpreter's implementation.
Q: Which PHP version does this source build?
This tree builds PHP 8.6 (the development master branch — 8.6.0-dev). The version constants live in main/php_version.h.
Q: Do I have to run make install?
No. The built binaries run in place (sapi/cli/php). Install only when you want them on your PATH and in system directories.
Q: What is the difference between php, php-cgi, and php-fpm?
php is the command-line interpreter (scripts, REPL, dev server). php-cgi is the CGI/FastCGI executable. php-fpm is the production FastCGI process manager that web servers connect to. See Section 7.
Q: How do I know which extensions are compiled in?
Run php -m. For details on one extension, php --ri <name>.
Q: Why does extension=opcache not work?
OPcache is a Zend extension. Load it with zend_extension=opcache.
Q: How do I use a different php.ini for one command?
php -c /path/to/php.ini script.php, or php -n script.php to ignore all INI files.
Q: Can I set an INI value just for one run?
Yes: php -d memory_limit=512M script.php. Repeat -d for multiple values.
Q: Is the built-in web server safe for production?
No. php -S is for development only. Use php-fpm behind nginx/Apache for production.
Q: How do I build a minimal PHP for hacking on the engine?
./configure --disable-all --enable-debug && make -j$(nproc). This skips optional extensions and builds fast.
Q: NTS vs ZTS — which do I have?
php -v prints (NTS) for non-thread-safe or (ZTS) for thread-safe (Zend Thread Safety). NTS is the standard choice for CLI/FPM; ZTS is for threaded SAPIs.
Q: How do I report a bug I found while building or testing?
Open an issue at github.com/php/php-src/issues. Reference it in commits as GH-NNNNNN.
Q: Where do additional (non-bundled) extensions come from?
The PECL repository. Scaffold your own with php ext/ext_skel.php --ext <name>.
Q: What does php --ini=diff show?
Only the INI entries whose current value differs from PHP's built-in default — the fastest way to audit what your php.ini actually changes.
14. Reference
CLI Option Reference
Complete option table for the php (cli) binary, from sapi/cli/php_cli.c:
| Short | Long | Arg | Description |
|---|---|---|---|
-a |
--interactive |
— | Run as interactive shell (requires readline). |
-B |
--process-begin |
code | Run PHP code before processing input lines. |
-C |
--no-chdir |
— | Do not chdir to the script's directory (CGI compat). |
-c |
--php-ini |
path | Look for php.ini in this directory/file. |
-d |
--define |
foo[=bar] | Define an INI entry for this run. |
-E |
--process-end |
code | Run PHP code after processing all input lines. |
-e |
--profile-info |
— | Generate extended info for debugger/profiler. |
-F |
--process-file |
file | Run a file for every input line. |
-f |
--file |
file | Parse and execute a file. |
-h |
--help |
— | Show help. |
-i |
--info |
— | Print phpinfo(). |
-l |
--syntax-check |
— | Syntax check only (lint). |
-m |
--modules |
— | Show compiled-in modules. |
-n |
--no-php-ini |
— | Do not load any php.ini. |
-q |
--no-header |
— | Suppress HTTP headers (CGI compat). |
-R |
--process-code |
code | Run code for every input line. |
-H |
--hide-args |
— | Hide passed arguments from external tools. |
-r |
--run |
code | Run code without <?php ?> tags. |
-s |
--syntax-highlight |
— | Output HTML-highlighted source. |
-S |
--server |
addr:port | Start the built-in web server. |
-t |
--docroot |
dir | Document root for the built-in server. |
-w |
--strip |
— | Output source with comments/whitespace stripped. |
-v |
--version |
— | Print version. |
| — | --rf/--rfunction |
name | Reflect a function. |
| — | --rc/--rclass |
name | Reflect a class. |
| — | --re/--rextension |
name | Reflect an extension. |
| — | --rz/--rzendextension |
name | Reflect a Zend extension. |
| — | --ri/--rextinfo |
name | Show an extension's configuration. |
| — | --ini |
[diff] | Show config file names (=diff shows changed entries). |
Common ./configure switches
Feature/SAPI toggles (--enable-NAME):
cli cgi fpm embed phpdbg litespeed opcache-jit debug
debug-assertions ipv6 dtrace gcov short-tags fd-setsize
address-sanitizer undefined-sanitizer memory-sanitizer werror
Extension toggles — no external lib (--enable-NAME):
bcmath calendar ctype dba dom exif fileinfo filter ftp gd
intl mbstring mbregex mysqlnd pcntl pdo phar posix session
shmop simplexml soap sockets sysvmsg sysvsem sysvshm
tokenizer xml xmlreader xmlwriter zend-test
Extension toggles — link a system library (--with-NAME[=DIR]):
curl openssl zlib bz2 zip gmp gettext iconv ldap ldap-sasl
sodium snmp tidy xsl enchant ffi readline libedit libxml
mysqli pgsql pdo-mysql pdo-pgsql pdo-sqlite sqlite3 pdo-odbc
pdo-firebird pdo-dblib freetype jpeg webp avif xpm password-argon2
apxs2 capstone
Build paths:
--prefix=PATH installation prefix (default /usr/local)
--with-config-file-path=PATH directory PHP searches for php.ini
--with-config-file-scan-dir=PATH extra directory of *.ini fragments
--with-layout=TYPE file layout (PHP or GNU)
--disable-all build minimal; add only what you enable
Selected php.ini directives (production defaults)
| Directive | Default | Directive | Default |
|---|---|---|---|
engine |
On |
short_open_tag |
Off |
precision |
14 |
serialize_precision |
-1 |
output_buffering |
4096 |
implicit_flush |
Off |
zend.enable_gc |
On |
zend.exception_ignore_args |
On |
expose_php |
On |
max_execution_time |
30 |
max_input_time |
60 |
memory_limit |
128M |
error_reporting |
E_ALL & ~E_DEPRECATED |
display_errors |
Off |
display_startup_errors |
Off |
log_errors |
On |
variables_order |
"GPCS" |
request_order |
"GP" |
post_max_size |
8M |
default_charset |
"UTF-8" |
enable_dl |
Off |
file_uploads |
On |
upload_max_filesize |
2M |
max_file_uploads |
20 |
allow_url_fopen |
On |
allow_url_include |
Off |
default_socket_timeout |
60 |
cli_server.color |
On |
session.save_handler |
files |
session.use_strict_mode |
1 |
session.use_only_cookies |
1 |
session.name |
PHPSESSID |
session.cookie_httponly |
1 |
session.cookie_samesite |
"Lax" |
session.gc_maxlifetime |
1440 |
session.cache_limiter |
nocache |
Bundled SAPIs
cli cgi fpm phpdbg embed apache2handler litespeed fuzzer
Useful links
- PHP language manual: php.net/docs
- Installation guide: php.net/install
- Windows binaries: windows.php.net
- Internal/implementation docs: php.github.io/php-src
- Extension library: PECL
- Issues: github.com/php/php-src/issues