Installing and Running PHP
Installing PHP is not finished when a package appears on the machine. A project needs the correct PHP version, the correct active binary, the required extensions, a suitable php.ini, and a way to prove all of that from the terminal.
This lesson is about verification. Installation steps differ by operating system, but the checks that prove PHP is ready are the same professional habit everywhere.
Common Ways PHP Gets Installed
PHP can come from several places:
- an operating-system package manager
- Homebrew on macOS
- a Windows installer or zip distribution
- a development stack such as XAMPP, Laragon, MAMP, or Herd
- Docker or another container image
- a version manager
- a compiled-from-source build
Those options can install PHP into different directories. A machine can also have more than one PHP version installed at the same time.
That is why the first check is always the active binary.
Find The Active PHP Binary
On macOS and Linux:
which php
php -v
On Windows PowerShell:
where php
php -v
Example output:
/usr/bin/php
PHP 8.5.6 (cli)
The path tells you which executable your shell found. The version tells you what that executable actually runs.
If a project expects PHP 8.3 and php -v shows PHP 8.1, the problem is not your application code. It is the runtime.
Check Configuration Files
PHP loads configuration from php.ini and optional additional .ini files.
php --ini
Typical output includes:
Loaded Configuration File: /etc/php.ini
Scan for additional .ini files in: /etc/php.d
This matters because CLI PHP and web PHP may not load the same configuration. If you install an extension for one runtime but not the other, the terminal and browser can behave differently.
Check Extensions
Extensions provide features that many projects rely on.
php -m
php -m | grep pdo
php -m | grep mbstring
On Windows PowerShell:
php -m
php -m | Select-String pdo
php -m | Select-String mbstring
From PHP code:
<?php
declare(strict_types=1);
$requiredExtensions = ['mbstring', 'json', 'pdo'];
foreach ($requiredExtensions as $extension) {
echo $extension . ': ';
echo extension_loaded($extension) ? 'loaded' : 'missing';
echo PHP_EOL;
}
// Prints:
// mbstring: loaded
// json: loaded
// pdo: loaded
Missing extensions often produce confusing framework or Composer errors. Checking them directly is faster than guessing.
Use Composer Platform Checks
Composer projects can declare required PHP versions and extensions in composer.json.
{
"require": {
"php": "^8.3",
"ext-mbstring": "*",
"ext-pdo": "*"
}
}
After installing PHP, run:
composer check-platform-reqs
This checks the installed PHP runtime against the project's declared requirements. It is a strong signal that your machine matches the project closely enough to start working.
Run A First Script
Create hello.php:
<?php
declare(strict_types=1);
echo 'Hello from PHP ' . PHP_VERSION . PHP_EOL;
// Prints:
// Hello from PHP 8.5.6
Run it:
php hello.php
Then syntax-check it:
php -l hello.php
This proves PHP can execute a script from your shell.
Run A First Local Web Request
Create public/index.php:
<?php
declare(strict_types=1);
header('Content-Type: text/plain');
echo 'Hello over HTTP' . PHP_EOL;
echo 'SAPI: ' . PHP_SAPI . PHP_EOL;
// Browser output:
// Hello over HTTP
// SAPI: cli-server
Start the built-in server:
php -S 127.0.0.1:8000 -t public
Open:
http://127.0.0.1:8000/
This proves PHP can handle a local HTTP request. It does not prove production PHP-FPM or a real web server is configured.
Choose An Installation Model Deliberately
The best installation method is the one the project can document, reproduce, update, and remove safely. Different models solve different problems.
Host Package Or Version Manager
Installing PHP on the host gives fast CLI startup and straightforward editor integration. It suits course exercises and projects where the team can maintain compatible host versions.
The tradeoff is host drift. Developers can have different patch releases, extensions, INI settings, package repositories, or executable order. A version manager can reduce version switching friction, but the project still needs documented commands and extension setup.
Development Stack
Stacks such as XAMPP, MAMP, Laragon, or Herd can provide PHP and related services with a friendly setup. They can be useful for beginners or teams standardised on that tool.
Understand which executable their terminal command uses. A stack's web server may use its bundled PHP while a separate shell resolves an operating-system PHP. "The stack says PHP 8.5" does not prove php -v in an unrelated terminal uses it.
Containerized Runtime
A container image can pin PHP, extensions, operating-system packages, and services close to project configuration. This improves consistency when the team uses the same image definition.
It adds a container-provider dependency, filesystem and networking boundaries, and a command wrapper. Decide whether project tools run inside the container or on the host. Running Composer with host PHP and tests with container PHP can resolve or execute against different platforms.
For a container project, the correct verification command may be project-specific:
docker compose exec app php -v
Do not copy that command unless the repository actually defines an app service. Follow its documented service name and wrapper scripts.
Compiling From Source
A source build provides precise compile-time control and is valuable for PHP development, unusual targets, or specialised runtime images. It is rarely the simplest beginner workstation installation. The team becomes responsible for build flags, external libraries, security updates, and reproducibility.
Install From A Trusted Source
Use the official PHP documentation and a maintained package source appropriate to the operating system. Avoid downloading an executable from an arbitrary tutorial mirror or running an unreviewed installation script with administrator privileges.
Before installation, know:
- who publishes the package or image;
- which PHP branches it provides;
- how security updates arrive;
- where configuration and extensions are stored;
- how to uninstall or roll back it;
- whether the project supports that distribution.
Package names and supported repositories change. Operating-system-specific lessons provide a process, but current installation commands should be verified against maintained documentation at the time of use.
Separate Installation From Activation
Installing a second PHP version does not necessarily change the php command. The shell still searches PATH and runs the first matching executable. Package links, version-manager shims, aliases, shell profiles, and application launchers can all affect resolution.
Use a command-resolution check that matches the shell. On a POSIX shell, command -v php is defined by the shell and reports the selected command. which is common but can be an external utility with platform-specific behaviour.
command -v php
php -v
PowerShell can show richer command information:
Get-Command php | Format-List Source, CommandType
php -v
After changing PATH, restart the terminal or reload its profile as required. Some shells cache command locations; opening a new terminal is a simple way to avoid diagnosing stale resolution state.
An IDE can launch a different interpreter from the one in its integrated terminal. Record the configured interpreter path when debugging editor tests or analysis that disagree with manual commands.
Do Not Mix Installation Owners Accidentally
A common maintenance problem is one PHP installed by the operating system, another by a third-party package manager, another bundled in a development stack, and a fourth supplied by a version manager. Multiple versions are valid when they have clear ownership. Unplanned overlap makes upgrades and extension installation unpredictable.
Before adding another installation, inventory existing commands and project requirements. Do not overwrite system-managed files manually or copy an extension binary between unrelated PHP builds. Extensions must match the PHP API, architecture, thread-safety mode, and operating-system dependencies of the runtime loading them.
When an extension is missing, install it through the same ownership model as PHP whenever possible. For example, use the distribution's matching extension package or rebuild the controlled image. Then verify it with the exact active binary.
Verify More Than A Version String
A successful php -v is necessary but not sufficient. Installation acceptance should include:
| Check | What it proves |
|---|---|
| Command resolution | The shell selects the intended executable |
| Version output | The selected executable is an acceptable release |
php --ini |
Configuration sources are visible |
| Required extension checks | The runtime exposes project capabilities |
php -l |
The runtime can parse the source language level |
| Script execution | The runtime can execute local files and emit output |
| Composer platform check | Declared project PHP and extension requirements are satisfied |
| Local HTTP smoke test | The selected development server can reach the intended public entry point |
A platform check does not run the application's tests, and a successful test suite does not prove every production extension or service is configured. Each check has a bounded claim.
Keep The Installation Maintainable
Record how updates are applied. PHP patch releases include bug and security fixes, but an update can also interact with extensions and dependencies. Use the project's test and smoke-check workflow after changing the runtime.
Avoid permanently pinning a workstation to an unsupported branch merely because one old project needs it. Isolate legacy requirements with a version manager or container where appropriate, and plan the application upgrade separately.
When removing an unused PHP installation:
- confirm no project, service, IDE, or scheduled task still references its path;
- preserve intentional configuration changes;
- uninstall it through the tool that installed it;
- remove obsolete
PATHentries or aliases; - open a new shell and verify the remaining runtime;
- rerun project platform and test checks.
Manual deletion can leave package metadata, services, configuration, or broken links behind.
Avoid Administrator Execution As A Shortcut
Normal PHP scripts, Composer installs, and course exercises should not require administrator or root execution. Running development tools with elevated privileges can create files owned by the wrong user and gives application code unnecessary authority.
Use administrator privileges only for the narrow operating-system package action that requires them. Then return to an ordinary account for project work. If PHP cannot read a project file without elevation, investigate file ownership and permissions rather than making root execution the standard command.
What To Record For A Project
For a real project, make setup reproducible by recording:
- required PHP version
- required extensions
- how PHP is installed locally
- how to find the active binary
- how to check
php.ini - how to run the local server or container
- how to run Composer's platform check
This belongs in project setup documentation because future developers will hit the same environment questions.
What You Should Be Able To Do
After this lesson, you should be able to verify an installed PHP runtime, identify the active binary, inspect loaded configuration, check required extensions, run a PHP script, and start a local HTTP server.
For junior PHP work, this matters because many setup bugs are environment bugs. A developer who can prove the runtime is correct can unblock themselves and help teammates faster.
Practice
Practice: Produce An Installation Acceptance Note
Create a setup note that proves a PHP CLI installation is ready for a project.
Requirements
Include operating-system-appropriate commands that establish:
- the selected executable path and PHP version;
- the loaded primary and scanned INI configuration;
- loaded modules;
- syntax validation and execution of a small
hello.php; - Composer platform requirements, when the directory is a Composer project.
The script must print the PHP version, SAPI, and binary path with expected-output comments. For every command, state the bounded claim it proves and one thing it does not prove.
Finish by recording the installation owner, such as an operating-system package manager, Homebrew, a version manager, a development stack, or a container image. Explain why this ownership matters for upgrades and removal.
Show solution
command -v php
php --version
php --ini
php -m
php -l hello.php
php hello.php
composer check-platform-reqs
In PowerShell, replace the first command with:
Get-Command php | Format-List Source, CommandType
A suitable hello.php is:
<?php
declare(strict_types=1);
echo 'Version: ', PHP_VERSION, PHP_EOL;
echo 'SAPI: ', PHP_SAPI, PHP_EOL;
echo 'Binary: ', PHP_BINARY, PHP_EOL;
// Output shape:
// Version: <installed version>
// SAPI: cli
// Binary: <selected executable path>
The command-resolution and version checks identify the CLI executable selected by this shell. They do not identify a separate PHP-FPM or container runtime. php --ini identifies CLI configuration sources but does not prove every setting is suitable. php -m lists loaded CLI modules but does not prove application behaviour. Linting proves syntax validity for that file; execution proves the process can run it. Composer's platform check compares declared requirements but does not replace tests.
Record the installation owner explicitly, for example Homebrew formula php@8.5 or project Docker image. Updates, extensions, rollback, and removal should use that same owner. Without it, a later developer may install a competing runtime or delete files manually and leave the environment inconsistent.
Task: Resolve A Conflicting Active Binary
A developer installed PHP 8.5, but php -v still reports PHP 8.2 and Composer rejects a dependency requiring PHP 8.3 or newer.
Create a diagnostic checklist for macOS/Linux and Windows PowerShell.
Requirements
- Identify every command named
phpvisible to the shell where possible. - Record the selected executable, its version, and loaded INI files.
- Check aliases, version-manager shims, IDE interpreters, and container commands where relevant.
- Explain how opening a new terminal can affect
PATHchanges or command caches. - Choose one installation owner to control activation rather than deleting executables manually.
- Verify Composer and PHP use the intended runtime before changing application dependencies.
Show solution
type -a php
command -v php
php -v
php --ini
In PowerShell:
Get-Command php -All
Get-Command php | Format-List Source, CommandType
php -v
php --ini
type -a or Get-Command -All can reveal competing commands. The selected path and version show which one currently owns php. Inspect shell aliases, version-manager state, and profile PATH entries before changing anything.
If the project runs in a container, compare the host output with its documented command, such as a Compose service wrapper. Also inspect the PHP interpreter configured in the IDE when editor tools disagree with the terminal.
Activate PHP 8.5 through the package manager, version manager, stack, or container configuration that installed it. Do not manually delete the PHP 8.2 executable, because it may be operating-system managed or required by another project.
Open a new terminal after changing PATH or activation. Then rerun:
php -v
php --ini
composer check-platform-reqs
Proceed only when the selected path and version are intentional and Composer's platform check runs under that same environment. A dependency change would not fix a shell that is still executing the wrong interpreter.
Task: Verify Required Extensions And Drivers
Create a command-line checker for a project requiring json, mbstring, pdo, and the MySQL PDO driver.
Requirements
- Print one labelled line per extension.
- Check
PDO::getAvailableDrivers()separately fromextension_loaded('pdo'). - Send a concise missing-requirements summary to
STDERR. - Exit with status
1when any requirement is missing and0otherwise. - Keep expected successful output in comments.
- Explain why copying an extension binary from a different PHP installation is unsafe.
- Relate the script to Composer requirements such as
ext-mbstringandext-pdowithout claiming Composer installs them.
Show solution
<?php
declare(strict_types=1);
$requiredExtensions = ['json', 'mbstring', 'pdo'];
$missing = [];
foreach ($requiredExtensions as $extension) {
$loaded = extension_loaded($extension);
echo $extension, ': ', $loaded ? 'loaded' : 'missing', PHP_EOL;
if (!$loaded) {
$missing[] = 'extension ' . $extension;
}
}
$pdoDrivers = extension_loaded('pdo') ? PDO::getAvailableDrivers() : [];
$mysqlAvailable = in_array('mysql', $pdoDrivers, true);
echo 'PDO MySQL driver: ', $mysqlAvailable ? 'available' : 'missing', PHP_EOL;
if (!$mysqlAvailable) {
$missing[] = 'PDO MySQL driver';
}
if ($missing !== []) {
fwrite(STDERR, 'Missing requirements: ' . implode(', ', $missing) . PHP_EOL);
exit(1);
}
exit(0);
// Successful output:
// json: loaded
// mbstring: loaded
// pdo: loaded
// PDO MySQL driver: available
The base PDO extension and a concrete database driver are separate requirements. A runtime can load PDO while reporting no MySQL driver.
Extension binaries are compiled for a particular PHP API, architecture, thread-safety mode, and operating-system environment. Copying one from another installation can fail to load or destabilise the process. Install the matching extension through the same package, image, or build system that owns PHP.
Composer can declare ext-mbstring and ext-pdo, and composer check-platform-reqs can detect their absence. The operating system or container still has to install and enable them; Composer does not supply PHP extensions.