Jesse A. Green / notebook

PHP Interpreter (php-src) — User Guide

Generated June 2026 from php/php-src at 95b5b48

AI-generated documentation. The library is checked by sampling (three repositories so far); this guide was not individually reviewed. Verify against the project before relying on it.

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

  1. Quick Start
  2. What You Are Building
  3. Requirements
  4. Building PHP From Source
  5. Running the PHP CLI (php)
  6. The Built-in Web Server
  7. The Other SAPIs (php-cgi, php-fpm, phpdbg)
  8. Configuring PHP with php.ini
  9. Extensions
  10. Common Tasks
  11. Running the Test Suite
  12. Troubleshooting
  13. FAQ
  14. 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 install to use the binary. After a build, the CLI lives at sapi/cli/php inside the source tree and runs in place — ideal for testing changes.

Note

On a minimal Git build you need autoconf, bison, and re2c. A default build additionally needs libxml2 and libsqlite3. 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 bison is usually too old. Homebrew/MacPorts install a newer bison that is not on the default PATH. Add it before running ./buildconf (Homebrew prints the exact export PATH=... line after install).

Prebuilt binaries (skip building entirely)

If you only want to run PHP, you do not need this repository:

  • Windows: download *.exe builds 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, configure already exists and you can skip ./buildconf. On a Git checkout you must run it. Use ./buildconf --force if configure is 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 install and call sapi/cli/php directly 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 -r you 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-readline or --with-libedit). Without it, -a falls 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 opcache is 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=value can be repeated. These overrides apply only to that single invocation, layered on top of the loaded php.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-fpm behind nginx/Apache, or mod_php — see the Admin Guide.

Tip

Colorized CLI server output is controlled by the cli_server.color INI directive (On in the production template). Bind to 0.0.0.0:8000 to 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-fpm over php-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 -t after 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.php disassembles 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

  1. Built-in defaults compiled into PHP.
  2. The main php.ini (location set at build time, overridable with -c).
  3. Extra *.ini files in the scan directory (--with-config-file-scan-dir).
  4. Per-invocation -d key=value overrides (CLI) or php_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 = Off and allow_url_include = Off on 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 accept K, M, G suffixes (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/standard and ext/spl are always present — they provide the core function library and standard data structures. pcre, date, hash, json, and random are 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-NAME is 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-all plus explicit --enable/--with flags 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, not extension=. 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, run make clean (or git clean -xfd to 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=16M allocates JIT memory (enabling the JIT in tests).
  • --repeat 2 re-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-debug and one of --enable-address-sanitizer (fast, needs rebuild) or run under valgrind via -m --show-mem in TEST_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