Your country

Tools that support it use your country for local currency, number formats, units and paper size. Your choice is saved only in this browser.

Type a name or a two-letter code. Use the up and down arrow keys to move through the countries, Enter to choose one and Escape to close.

PHP (8.5)  Module 1 – Start here: PHP in 2026

Install PHP 8.5 and check your setup

Install PHP 8.5 on Windows, macOS or Linux, check it with php -v, php -m and php --ini, and set up a development php.ini that shows and logs errors.

  • Beginner
  • 10 minutes
  • Examples run with PHP 8.5.11 and Python 3.14.8
  • By MySmartCoPilot
Free lesson, Pro answers: 10 minutes
Free: the whole lesson. With a pass: the model answers to its 2 interview questions.

What you will learn

  • Choose a way to install PHP 8.5 on Windows, macOS or Linux, or in a container, that keeps getting security fixes
  • Inspect an installation's version, build type and extensions with php -v and php -m
  • Find which php.ini file PHP reads with php --ini, and in which order it looks for one
  • Create a development php.ini that shows and logs every error and sets a time zone

Before you start

What you’ll learn · Before you start

What you will learn

  • Choose a way to install PHP 8.5 on Windows, macOS or Linux, or in a container, that keeps getting security fixes
  • Inspect an installation's version, build type and extensions with php -v and php -m
  • Find which php.ini file PHP reads with php --ini, and in which order it looks for one
  • Create a development php.ini that shows and logs every error and sets a time zone

Before you start

On this page

There are five common ways to put PHP on a computer, and they differ in what matters most later: whether security fixes reach you, and which branch you get at all. Ubuntu 24.04’s own package installs PHP 8.3, for example, and the newest XAMPP bundle for Windows ships PHP 8.2.12, a branch whose security fixes end with 2026.

This lesson helps you pick an install for your computer, then checks it the way you will check every PHP setup from now on: the version and the build with php -v, the extensions with php -m, the settings file with php --ini, and finally a development php.ini that shows and logs every error.

Choose an install that keeps getting security fixes

Five ways cover most setups. Each one gives you the same PHP language, but who updates it, and to which branch, is different:

  • Windows: the zip from php.net. Pick the VS17 x64 Non Thread Safe build. The download page says Non Thread Safe builds are for the command line and FastCGI, and Thread Safe builds for PHP loaded as a module into a web server. It also needs Microsoft’s Visual C++ Redistributable for Visual Studio 2015-2022. Unzip it to a folder such as C:\php, add that folder to the PATH variable without overwriting what is there, and copy php.ini-development to php.ini in the same folder.
  • macOS: Homebrew. brew install php installs the current branch, 8.5, with ready-built packages for Apple silicon, and puts its php.ini in etc/php/8.5 under the Homebrew folder. Older branches have formulae of their own, such as php@8.4.
  • Linux: the distribution’s packages. Check the branch before you install, with apt policy php or dnf info php. Ubuntu 24.04 LTS ships 8.3, Ubuntu 26.04 LTS ships 8.5 and Debian 13 ships 8.4, and the distribution’s security team, not php.net, decides how long they are patched.
  • Containers: the official Docker image. docker run --rm php:8.5-cli php -v starts a clean PHP 8.5 without installing anything else. Tags pin the branch and even the patch release, such as 8.5.11-cli, and the image comes in cli, fpm, apache and zts variants.
  • A bundled stack. Installers such as XAMPP put Apache httpd, a database and PHP on a computer in one step. Their PHP is whatever the bundle ships, and XAMPP’s own FAQ says it is not meant for production use but only for development.

Three questions about your own setup decide most of the choice. Answer them, and the table marks the ways that fit and gives the reason under each one that does not:

Interactive · answer and compare Which way of installing PHP fits your computer? Answer the three questions. The table marks the ways that fit, and gives the reason under each one that does not.
Which system do you develop on?
Must your computer run the same PHP branch as a server you deploy to?
Do you need several PHP branches side by side, one per project?

Answer the questions above: the table then marks what fits your case and says why the rest does not.

Five ways to install PHP against four things a setup needs
Way to install Security updates Choice of branch Adding extensions Setup
Windows zip from php.net What you get: php.exe and its extensions in one folder Mixed you download each new patch release yourself Good every supported branch; x64 Non Thread Safe suits the command line Mixed DLLs in the ext folder, each switched on with an extension= line Mixed unzip, add the folder to PATH, copy a php.ini template
Homebrew on macOS What you get: brew install php, which is 8.5 Good brew upgrade installs new patch releases Good php is 8.5; php@8.4, php@8.3 and php@8.2 are separate formulae Mixed the common ones are built in; others come from PIE or PECL Good one command, with php.ini in etc/php/8.5 under the Homebrew folder
Linux packages What you get: the distribution's own PHP Good security updates from the distribution, by its own policy Poor one branch per release: Ubuntu 24.04 has 8.3, Debian 13 has 8.4 Good one package per extension, such as php8.4-mbstring Good one apt or dnf command
Docker image What you get: PHP in a container, such as php:8.5-cli Mixed pull the new tag and rebuild your image Good a tag for every branch and patch release, such as 8.5.11-cli Mixed docker-php-ext-install builds them into your own image Mixed needs Docker, and PHP runs inside the container
Bundled stack What you get: web server, database and PHP in one installer Poor its PHP changes only with a new bundle; XAMPP's newest for Windows has 8.2.12 Poor the branch the bundle ships, whatever is current Good the common ones ready, switched on in its php.ini Good one installer with Apache httpd and a database
How the answers decide
  • “Which system do you develop on?” Windows: rules out Homebrew on macOS and Linux packages. Homebrew and Linux packages are for macOS and Linux; on Windows they work only inside WSL, a Linux system that runs on Windows.
  • “Which system do you develop on?” macOS: rules out Windows zip from php.net and Linux packages. The php.net zip is built for Windows and the packages for Linux, so neither runs on macOS.
  • “Which system do you develop on?” Linux: rules out Windows zip from php.net and Homebrew on macOS. The php.net zip is built for Windows, and Homebrew is the macOS route; on Linux the distribution's packages or a container take their place.
  • “Must your computer run the same PHP branch as a server you deploy to?” Yes, the same branch: adds a caveat to Linux packages and Bundled stack. They ship one fixed branch, which may not be the server's; a container tag pins the branch exactly.
  • “Do you need several PHP branches side by side, one per project?” Yes, several: adds a caveat to Windows zip from php.net, Linux packages and Bundled stack. One branch at a time, unless you keep several folders or packages yourself; containers give each project its own.

In short: Homebrew on macOS, the php.net zip on Windows, the distribution’s packages on Linux when they ship the branch you need, and a container whenever you must match a server exactly or keep several branches side by side. A bundle is fine for a first look, as long as you know its branch and keep it off any network you do not control.

Checkpoint

Check: Choosing how to install PHP

  1. Question 1 of 2 You install PHP 8.5 on 64-bit Windows to run scripts from the command line and with the built-in server. Which zip from php.net do you pick?

    Choose one answer.

    Show the answer: Question 1 of 2

    Answer: VS17 x64 Non Thread Safe

    For the command line, pick x64 Non Thread Safe. Thread Safe builds exist for PHP running as a module inside a threaded web server.

  2. Question 2 of 2 A server runs Ubuntu 24.04 LTS, and the site needs PHP 8.4. What does sudo apt install php give you?

    Choose one answer.

    Show the answer: Question 2 of 2

    Answer: PHP 8.3, the branch that Ubuntu 24.04 ships

    Check the branch a distribution ships before you install, with apt policy php or dnf info php. A different branch needs a newer release of the distribution or another source, such as an official container image.

Check the version and the extensions you installed

Whatever you installed, open a new terminal so that it sees the new PATH, and ask PHP what it is. The first command names the version and the build, the second lists loaded extension: A module that adds functions and classes to PHP, such as mbstring, intl, pdo_sqlite or sodium. php -m lists the extensions an installation has loaded., filtered here to the ones later lessons of this track rely on: PDO with its drivers, mbstring, intl and sodium:

php -v and php -m Python · versions_session.py
# The commands of this session, as you would type them in a terminal; the output shows what they printed.
from session import run

run("""
php -v
php -m | grep -i -E 'pdo|mbstring|intl|sodium'
""")

Output

$ php -v
PHP 8.5.11 (cli) (NTS)
Copyright (c) The PHP Group
Zend Engine v4.5.11, Copyright (c) Zend Technologies
    with Zend OPcache v8.5.11, Copyright (c), by Zend Technologies
$ php -m | grep -i -E 'pdo|mbstring|intl|sodium'
intl
mbstring
PDO
pdo_mysql
pdo_pgsql
pdo_sqlite
sodium

Recorded with Python 3.14.8 on macOS 26 arm64. To run it yourself: mise exec python@3.14.8 -- python3 versions_session.py

The first line of php -v reads PHP 8.5.11 (cli) (NTS): the version, the SAPI in brackets, and the build type. NTS is a NTS build: A Non Thread Safe build of PHP, the usual build for the command line and PHP-FPM. A Thread Safe (TS or ZTS) build is needed when PHP runs as a module inside a threaded web server., the one the command line and PHP-FPM use; a thread-safe build says ZTS instead. The last line says OPcache, PHP’s cache of compiled scripts, is part of this build.

php -m prints every loaded module, one per line, and the session filtered it with grep. On Windows, findstr does the same job. A script can check for itself, and the next program does: it prints the build, the settings file PHP read, four settings and whether seven extensions are loaded. Run it on your own computer after you install:

A report on your PHP setup PHP · env_report.php
<?php

// What this PHP is, which settings file it read, and whether the extensions this track uses are loaded.
printf("PHP %s, %s SAPI, %s\n", PHP_VERSION, PHP_SAPI, PHP_ZTS ? 'thread safe (ZTS)' : 'not thread safe (NTS)');
$ini = php_ini_loaded_file();
echo 'php.ini: ', $ini === false ? 'none loaded' : $ini, "\n";

echo "Settings:\n";
printf("  display_errors   %s\n", ini_get('display_errors'));
printf("  error_reporting  %s\n", error_reporting() === E_ALL ? 'E_ALL' : error_reporting());
printf("  log_errors       %s\n", ini_get('log_errors') ? 'on' : 'off');
printf("  date.timezone    %s\n", date_default_timezone_get());

echo "Extensions:\n";
foreach (['mbstring', 'intl', 'pdo_sqlite', 'sodium', 'openssl', 'dom', 'curl'] as $extension) {
    printf("  %-11s %s\n", $extension, extension_loaded($extension) ? 'loaded' : 'MISSING');
}

Output

PHP 8.5.11, cli SAPI, not thread safe (NTS)
php.ini: none loaded
Settings:
  display_errors   1
  error_reporting  E_ALL
  log_errors       off
  date.timezone    UTC
Extensions:
  mbstring    loaded
  intl        loaded
  pdo_sqlite  loaded
  sodium      loaded
  openssl     loaded
  dom         loaded
  curl        loaded

Recorded with PHP 8.5.11 (cli) (NTS) on macOS 26 arm64. To run it yourself: php env_report.php

In the recorded run every extension is loaded. On yours, a line may say MISSING. With the Windows zip, most extensions are files in the ext folder that load only when an extension= line in php.ini names them, and the manual notes that many such lines are already there behind a semicolon, which you remove. On Debian or Ubuntu, an extension is a package of its own, such as php8.4-mbstring. Extensions that do not come with PHP are installed with PIE, PHP’s installer for extensions.

Checkpoint

Check: Reading php -v and php -m

  1. Question 1 of 2 php -v prints PHP 8.5.11 (cli) (NTS). What does NTS tell you?

    Choose one answer.

    Show the answer: Question 1 of 2

    Answer: It is a Non Thread Safe build, the usual one for the command line and PHP-FPM

    The first line of php -v names the version, the SAPI in brackets and the build type: NTS (Non Thread Safe) or ZTS (thread safe).

  2. Question 2 of 2 On a Windows install, env_report.php prints mbstring MISSING, although php_mbstring.dll is in the ext folder. What is the fix?

    Choose one answer.

    Show the answer: Question 2 of 2

    Answer: Remove the semicolon in front of extension=mbstring in the php.ini that php --ini says is loaded

    Extensions of the Windows zip are DLLs in the ext folder, switched on by extension= lines. Edit the php.ini that php --ini reports, then run php -m again to see mbstring listed.

Find the settings file PHP reads

The report above printed php.ini: none loaded, because the recorded runs in this track use PHP’s built-in settings, with no php.ini: PHP's main settings file, read when PHP starts. php --ini shows which php.ini was loaded, if any, and which extra .ini files were read from the scan folder.. php --ini shows the same thing from the terminal, and PHP 8.5 added --ini=diff, which lists every setting that differs from its built-in default:

php --ini and php --ini=diff Python · ini_session.py
# The commands of this session, as you would type them in a terminal; the output shows what they printed.
from session import run

run("""
php --ini
php --ini=diff
""")

Output

$ php --ini
Configuration File (php.ini) Path: "…/php/8.5.11"
Loaded Configuration File:         (none)
Scan for additional .ini files in: "…/php/8.5.11/conf.d"
Additional .ini files parsed:      …/php/8.5.11/conf.d/php.ini
$ php --ini=diff
Non-default INI settings:
html_errors: "1" -> "0"
implicit_flush: "0" -> "1"
max_execution_time: "30" -> "0"

Recorded with Python 3.14.8 on macOS 26 arm64. To run it yourself: mise exec python@3.14.8 -- python3 ini_session.py

The four lines of php --ini answer four questions. The first is the folder where this build looks for its php.ini; … stands for the folder this PHP is installed in, and on your computer it is a full path, such as etc/php/8.5 inside the Homebrew folder. The second line says no php.ini was loaded. The third and fourth name the scan folder, conf.d, whose .ini files PHP reads after php.ini; this build has one file there, and since --ini=diff shows nothing from it, it sets nothing. The three lines that --ini=diff did print come from the command line itself: the manual lists them among the CLI’s own overrides, no HTML in error messages, output written at once and no time limit for scripts.

Each INI directive: One PHP setting, such as display_errors or date.timezone. Each has a built-in default that php.ini, the -d option of the php command or ini_set() can change. can come from several places, and PHP checks them in a fixed order. Step through it:

Interactive · stage by stage Where the php command looks for its settings Step through the places PHP checks when it starts. The first php.ini it finds wins; the scan folder and -d come after it.
Where the php command looks for its settings, step 8 of 8. Showing Was -c given? (php -c dev.ini), Is PHPRC set?, The compiled-in folder, No php.ini found (php --ini: (none) loaded), The scan folder, -d on the command line. In focus: Was -c given?, Is PHPRC set?, The compiled-in folder.foundfoundfoundWas -c given?php -c dev.iniIs PHPRC set?then look in that folderThe compiled-in foldershown by php --iniNo php.ini foundphp --ini: (none) loadedThe scan folderevery .ini file, A to Z-d on the command lineapplied last, so it wins

The drawing shows the whole scene; its 8 steps are listed below.

Every step as text
  1. One php.ini, the first found. When the php command starts, it looks for one php.ini in a fixed order, and the first place that has one wins. First comes -c, which names a file or a folder for this run.
  2. Found through -c. php -c dev.ini --ini loaded dev.ini in the session further down. PHP skips the other places and goes on to the scan folder.
  3. The PHPRC variable. Without -c, the PHPRC environment variable may name a folder to look in. On Windows the registry is checked next. The command line never looks in the current folder; other SAPIs do.
  4. The folder the build names. Then comes the folder compiled into the build, which php --ini prints as the Configuration File (php.ini) Path, and a php.ini there is the one PHP reads. On Windows the folder of php.exe is checked just before it.
  5. Nothing found. When no place has a php.ini, PHP runs with its built-in defaults. The PHP of the recorded runs reports Loaded Configuration File (none).
  6. The scan folder. Either way, PHP then reads every .ini file in its scan folder, in alphabetical order, and a later value replaces an earlier one. The official Docker image tells you to put your own settings there.
  7. -d wins. Last come -d options, such as php -d display_errors=0 script.php. Each sets one directive for this run only, over every file.
  8. A name for each SAPI. In each place, a file named for the SAPI, such as php-cli.ini for the command line, is used instead of php.ini. So the CLI and a web server can read different files from one folder.

When PHP reads the file matters as much as which file it reads. The manual says the command line reads php.ini on every run, while a server module reads it only once, when the web server starts. PHP-FPM is a long-running service as well, and keeps the settings it read at its start until it is restarted or reloaded. That is why an edit shows up in the terminal at once and on a website only after a restart.

Editing a file PHP never reads

php.ini-development and php.ini-production are templates: PHP reads neither until one is copied to the name and folder it looks for. And the php.ini that php --ini reports is the command line’s; PHP-FPM often reads another one. Before you edit, ask the PHP you care about which file it loaded.

Checkpoint

Check: Which php.ini PHP reads

  1. Question 1 of 2 You change date.timezone in the php.ini that php --ini reports, and a site served by PHP-FPM still shows the old zone. Why?

    Choose one answer.

    A hint

    When does each SAPI read php.ini?

    Show the answer: Question 1 of 2

    Answer: PHP-FPM read its settings when it started, and it may read another php.ini; restart it after checking which file it uses

    php --ini describes the command line. A web SAPI may load a different file and only reads it when it starts, so check the website's own php_ini_loaded_file() and restart PHP-FPM or the web server after an edit.

  2. Question 2 of 2 php --ini reports Loaded Configuration File: (none). Which settings is PHP using?

    Choose one answer.

    Show the answer: Question 2 of 2

    Answer: Its built-in defaults, plus whatever the scan folder's .ini files set

    (none) means no php.ini was found. PHP then runs with built-in defaults and the scan folder's files, which is why php --ini=diff showed only the command line's own three overrides.

A development php.ini shows every error and logs it

PHP comes with two php.ini templates. They differ mainly in who sees an error, which is what you change when you move from your own computer to a live site:

Directive php.ini-development php.ini-production
display_errors On Off
display_startup_errors On Off
error_reporting E_ALL E_ALL & ~E_DEPRECATED
log_errors On On
zend.exception_ignore_args Off On
zend.assertions 1 -1

Development shows every error, keeps the arguments of each call in exception traces and runs assertions. Production hides errors from visitors, leaves deprecation notices out, drops arguments from traces, where they could hold passwords, and does not compile assertions at all. Both log errors, but neither says where: neither template sets error_log, so you set it.

For your own computer, edit the php.ini that php --ini reported, or, when it reported none, copy php.ini-development to php.ini in the folder it named. Then set two directives in it: date.timezone, the zone your dates should use, such as Asia/Kolkata or Europe/London, because the built-in default is UTC; and error_log, the full path of a log file. This shorter file holds the settings that matter most, and the session below tries it with -c, which loads a file for one run without touching your real php.ini:

dev.ini INI · dev.ini
; Development settings: show every problem, and log it as well.
error_reporting = E_ALL
display_errors = On
display_startup_errors = On
log_errors = On
error_log = php-errors.log
date.timezone = Asia/Kolkata
warn.php PHP · warn.php
<?php

echo "Hello, $name\n";
Trying development settings with -c Python · devini_session.py
# The commands of this session, as you would type them in a terminal; the output shows what they printed.
from session import run

run("""
php -i | grep -E '^(display_errors|log_errors|error_log|date.timezone) '
php -c dev.ini --ini
php -c dev.ini --ini=diff
php -c dev.ini warn.php
cat php-errors.log
""")

Output

$ php -i | grep -E '^(display_errors|log_errors|error_log|date.timezone) '
display_errors => STDOUT => STDOUT
error_log => no value => no value
log_errors => Off => Off
date.timezone => UTC => UTC
$ php -c dev.ini --ini
Configuration File (php.ini) Path: "…/php/8.5.11"
Loaded Configuration File:         "dev.ini"
Scan for additional .ini files in: "…/php/8.5.11/conf.d"
Additional .ini files parsed:      …/php/8.5.11/conf.d/php.ini
$ php -c dev.ini --ini=diff
Non-default INI settings:
date.timezone: "UTC" -> "Asia/Kolkata"
error_log: (none) -> "php-errors.log"
error_reporting: (none) -> "30719"
html_errors: "1" -> "0"
implicit_flush: "0" -> "1"
log_errors: "0" -> "1"
max_execution_time: "30" -> "0"
$ php -c dev.ini warn.php
Warning: Undefined variable $name in warn.php on line 3
Hello,
$ cat php-errors.log
[…] PHP Warning:  Undefined variable $name in warn.php on line 3

Recorded with Python 3.14.8 on macOS 26 arm64. To run it yourself: mise exec python@3.14.8 -- python3 devini_session.py

php -i printed the built-in values first: errors shown, nothing logged, no log file, UTC. With -c dev.ini, the second command confirms which file was loaded, and --ini=diff lists what the file changed, beside the command line’s three overrides from before. error_reporting became 30719, the value of E_ALL since PHP 8.4. Then the warning appeared twice: on the screen, from display_errors, and in php-errors.log, from log_errors, with a time stamp that […] stands for and the word PHP in front. In a real php.ini, give error_log a full path, because a relative one depends on the folder PHP was started in.

Key idea

On your own computer, show every error and log it as well; on a live site, log every error and show none, and restart the server after each change to php.ini.

Checkpoint

Check: A development php.ini

  1. Question 1 of 2 php -c dev.ini --ini=diff prints log_errors: "0" -> "1". What does that line say?

    Choose one answer.

    Show the answer: Question 1 of 2

    Answer: The built-in default of log_errors is 0, and the loaded settings change it to 1

    Each line of --ini=diff is directive: default -> current value. It is the quickest way to see what a php.ini changes compared with PHP's own defaults.

  2. Question 2 of 2 A colleague copies the development php.ini to the live server "so that errors are easier to see". What should you tell them?

    Choose one answer.

    Show the answer: Question 2 of 2

    Answer: Use php.ini-production there; display_errors must be off for visitors, and errors go to a log you read

    Development settings show errors to whoever opens the page. On a live site use the production template: errors are logged, not displayed, and deprecation notices stay out of the log.

Practise: installing and checking PHP

This practice covers choosing an install, reading php -v and php -m, finding the php.ini and a development setup. Your weakest topic comes first, and every answer shows why it is right or what it misses:

Practice that adapts to you

Practise this lesson

12 questions about 4 ideas of this lesson. Each answer is explained at once, and what you get right is kept in this browser.

  1. Question 1 of 12 On macOS with Homebrew, which command installs the current PHP 8.5?

    Choose one answer.

    Show the answer: Question 1 of 12

    Answer: brew install php

    Homebrew's php formula installs the current branch with its php.ini in etc/php/8.5 under the Homebrew folder. Older branches have formulae of their own, such as php@8.4 and php@8.3.

  2. Question 2 of 12 A college lab installs the newest XAMPP for Windows, which bundles PHP 8.2.12. What should a student know about that PHP?

    Choose one answer.

    Show the answer: Question 2 of 12

    Answer: 8.2 receives security fixes only until the end of 2026, and the bundle's PHP changes only when a new bundle is released

    Bundled stacks are quick to set up for learning, but their PHP is whatever the bundle ships. Compare it with the supported branches, and never expose such a setup to a network you do not control.

  3. Question 3 of 12 Your laptop must run exactly the PHP of a server that runs 8.5.11 in a container, and other projects need 8.3. Which approach fits best?

    Choose one answer.

    Show the answer: Question 3 of 12

    Answer: Run each project in the official image with the exact tag, such as php:8.5.11-cli and a php:8.3 tag

    When versions must match exactly, or several branches run side by side, containers pin each one with a tag. The official image has tags for every branch and patch release.

  4. Question 4 of 12 Which command lists the extensions an installation has loaded?

    Choose one answer.

    Show the answer: Question 4 of 12

    Answer: php -m

    php -m lists loaded modules; piping it to grep, as the session did, answers "is pdo_sqlite there?" in one line. Inside a script, extension_loaded() gives the same answer.

  5. Question 5 of 12 env_report.php printed php.ini: none loaded on this page. What does that line print on a Homebrew install of PHP 8.5?

    Choose one answer.

    Show the answer: Question 5 of 12

    Answer: The path of the php.ini Homebrew installed, in etc/php/8.5 under the Homebrew folder

    php_ini_loaded_file() returns the path of the php.ini PHP read, or false when there was none. The runs on this page use PHP's built-in settings, so they print none loaded.

  6. Question 6 of 12 php -m on a server lists pdo_mysql, but the website fails with could not find driver. What is the most likely cause?

    Choose one answer.

    Show the answer: Question 6 of 12

    Answer: The website runs another PHP build or reads another php.ini, which does not load pdo_mysql

    Check extensions where the code runs: a temporary script on the site that prints extension_loaded('pdo_mysql'), or phpinfo() on a protected page, then delete it. The CLI and the web server often differ.

  7. Question 7 of 12 Put the places in the order the php command checks them for its php.ini (on Linux or macOS).

    Give each item its position, from 1 (first).

    Show the answer: Question 7 of 12

    Answer:

    1. The file or folder given with -c
    2. The folder in the PHPRC variable
    3. The folder compiled into the build

    -c comes first, then PHPRC, then the compiled-in folder that php --ini prints. If none has a php.ini, PHP uses its built-in defaults; the scan folder and -d options apply after the file either way.

  8. Question 8 of 12 What does the line "Scan for additional .ini files in" of php --ini name?

    Choose one answer.

    Show the answer: Question 8 of 12

    Answer: A folder whose .ini files PHP also reads, in alphabetical order, after php.ini

    The scan folder lets packages and container images add settings without editing php.ini. php --ini lists each file it parsed under Additional .ini files parsed.

  9. Question 9 of 12 dev.ini sets date.timezone = Asia/Kolkata. What does php -c dev.ini -d date.timezone=Europe/Paris -r 'echo date_default_timezone_get();' print?

    Choose one answer.

    Show the answer: Question 9 of 12

    Answer: Europe/Paris

    Files come first, the scan folder next, and -d options last. Use -d to try one setting for one run without editing any file.

  10. Question 10 of 12 Which settings does php.ini-development turn on that php.ini-production turns off?

    Choose every answer that is right.

    Show the answer: Question 10 of 12

    Answer:

    • display_startup_errors
    • display_errors

    The two templates differ in what they show, not in what they log: development displays errors, production hides them from visitors and leaves deprecation notices out of error_reporting.

  11. Question 11 of 12 With dev.ini, warn.php printed its warning and also wrote a line to php-errors.log. Which setting made PHP write that line?

    Choose one answer.

    Show the answer: Question 11 of 12

    Answer: log_errors = On, with error_log naming the file

    error_reporting picks the errors, display_errors shows them and log_errors with error_log writes them to a file. In development you see both copies; in production only the log.

  12. Question 12 of 12 You edit the development php.ini of a local PHP-FPM and nothing changes on your local site, while the command line shows the new values. What do you do?

    Choose one answer.

    Show the answer: Question 12 of 12

    Answer: Check the site's loaded php.ini with a temporary script, edit that file, and restart PHP-FPM

    The command line reads php.ini on every run; a server reads it when it starts. Confirm the file from the website itself, then restart the service so it reads the change.

Interview questions

Model answers open with any pass: ₹79 for 1 week ($2.99), one payment that never renews.

  1. Fresher · Warm-up

    What is the difference between php.ini-development and php.ini-production, and which one belongs on a live site?

    Both are templates that come with PHP; neither is read until you copy it to the php.ini path that php --ini shows. php.ini-development shows every problem: it sets display_errors and display_startup_errors on, reports every error level with E_ALL, keeps the arguments of functions in exception traces and runs assertions. That is what you want on your own computer. php.ini-production hides errors from visitors: display_errors and display_startup_errors are off, errors are logged instead, deprecation notices are not reported, exception traces leave out arguments and assertions are not compiled at all. A live site uses the production file, with error_log pointing at a file you read, because an error message shown to visitors can reveal paths, queries and settings.

  2. Fresher to senior

    On a Linux server, php -v reports PHP 8.4, but a page that prints PHP_VERSION shows 8.2, and code that needs 8.4 fails on the site. Why can the two differ, and how do you find and fix the PHP that serves the site?

    Model answer, Pro. Model answers open with any pass; prices are in the notice on this page. First step and follow-ups

  3. Fresher to senior

    You set memory_limit = 512M in php.ini. php -r 'echo ini_get("memory_limit");' now prints 512M, but a report on the website still stops with "Allowed memory size of 134217728 bytes exhausted". Walk through how you work out why, and how you make the change take effect.

    Model answer, Pro. First step and follow-ups

Key takeaways

  • Choose an install by who keeps it patched and which branch it gives you: the php.net zip on Windows, Homebrew on macOS, the distribution’s packages on Linux, and a container image when the branch must match a server.
  • php -v names the version, the SAPI and the build type, and php -m lists the loaded extensions; on Windows an extension loads only when an extension= line in the php.ini PHP reads names it.
  • php --ini shows the php.ini that was loaded and the scan folder, and php --ini=diff shows what differs from the built-in defaults; -c, PHPRC and the compiled-in folder are checked in that order, and -d wins over every file.
  • The command line reads php.ini on every run, while web servers and PHP-FPM read it when they start, so restart them after an edit.
  • A development php.ini shows and logs every error and sets date.timezone and error_log; a live site uses the production template, which logs errors and shows none.

Terms in this lesson

extension
A module that adds functions and classes to PHP, such as mbstring, intl, pdo_sqlite or sodium. php -m lists the extensions an installation has loaded.
INI directive
One PHP setting, such as display_errors or date.timezone. Each has a built-in default that php.ini, the -d option of the php command or ini_set() can change.
NTS build
A Non Thread Safe build of PHP, the usual build for the command line and PHP-FPM. A Thread Safe (TS or ZTS) build is needed when PHP runs as a module inside a threaded web server.
php.ini
PHP's main settings file, read when PHP starts. php --ini shows which php.ini was loaded, if any, and which extra .ini files were read from the scan folder.

References

Report a problem with this lesson

Quick answers and tool search

Type to search tools or to get a quick answer, for example 18% of 2500. Use the up and down arrow keys to move through the results, Enter to choose, and Escape to close.