start here

Managing Multiple PHP Versions

Real PHP developers often work on more than one project. One project may require PHP 8.2, another may require PHP 8.3, and a new project may already use PHP 8.5 features.

Managing multiple versions is about control. You need to know which version each project expects, which version your shell is running, which version the web server is running, and which extensions are available for that version.

The Project Decides The Version

The first place to check is usually composer.json.

{
  "require": {
    "php": "^8.3",
    "ext-mbstring": "*",
    "ext-pdo": "*"
  }
}

Then verify the active runtime:

php -v
composer check-platform-reqs

If Composer says your PHP version is not supported, do not change application code. Change or select the correct runtime.

Find Every Visible PHP Binary

On macOS or Linux:

which php
which -a php
php -v

On Windows PowerShell:

where php
php -v

The first path is the one your terminal uses. Other paths may belong to Homebrew, XAMPP, Laragon, MAMP, system packages, custom builds, or version managers.

Switching Versions

How you switch depends on your setup:

  • Homebrew can link a different formula.
  • Linux packages may provide versioned binaries such as php8.2 and php8.3.
  • Windows may switch by changing PATH order.
  • Tools such as Herd, Valet, asdf, phpenv, or containers can manage versions per project.
  • Docker pins the version in the image tag, such as php:8.3-fpm.

The exact tool matters less than the verification:

php -v
php --ini
php -m
composer check-platform-reqs

Run those after switching.

CLI And Web Versions Can Differ

One common mistake is switching CLI PHP but leaving the web runtime unchanged.

Example:

CLI: PHP 8.3
FPM: PHP 8.2

That can produce bugs where Composer works but the website fails, or the browser cannot use a syntax feature that works in terminal scripts.

Check CLI:

php -v
php --ini

Check FPM or the web runtime through service status, pool configuration, or a small web-only diagnostic route:

PHP example
<?php

declare(strict_types=1);

header('Content-Type: text/plain');

echo 'PHP: ' . PHP_VERSION . PHP_EOL;
echo 'SAPI: ' . PHP_SAPI . PHP_EOL;
echo 'Loaded ini: ' . (php_ini_loaded_file() ?: 'none') . PHP_EOL;

Do not leave this public in production. Use it temporarily in a safe environment or behind access control.

Extensions Are Version-Specific

Installing an extension for PHP 8.2 does not automatically make it available for PHP 8.3.

Check extensions after every version switch:

php -m
php -m | grep mbstring
php -m | grep pdo

From PHP:

PHP example
<?php

declare(strict_types=1);

foreach (['mbstring', 'intl', 'pdo'] as $extension) {
    echo $extension . ': ';
    echo extension_loaded($extension) ? 'loaded' : 'missing';
    echo PHP_EOL;
}

// Prints:
// mbstring: loaded
// intl: loaded
// pdo: loaded

If a project fails after switching PHP versions, missing extensions are one of the first things to check.

Containers Make Versions Explicit

Containers are often the cleanest way to pin project runtime versions.

FROM php:8.3-fpm

That image tag makes the expected version visible. You still need to install required extensions in the image and run checks inside the container:

php -v
php -m
composer check-platform-reqs

Do not rely on host PHP when the project actually runs in a container.

Upgrade Checks

When moving a project from one PHP version to another, verify more than syntax.

Useful checks:

php -v
composer check-platform-reqs
composer update --dry-run
php -l public/index.php

Also run the project's test suite and static analysis if available.

Look for:

  • removed or deprecated features
  • changed extension availability
  • dependencies that do not support the new PHP version
  • FPM service still running the old version
  • CI using a different version from local development

Version Notes Belong In The Project

A project should record:

  • required PHP version
  • local version switching tool
  • container image tag, if any
  • required extensions
  • how to verify CLI PHP
  • how to verify web PHP
  • how to run Composer platform checks

This avoids tribal knowledge and makes onboarding faster.

What You Should Be Able To Do

After this lesson, you should be able to identify a project's required PHP version, find all visible PHP binaries, switch or select the correct runtime, verify extensions, distinguish CLI from web PHP, and explain why containers can make version management clearer.

For junior PHP work, this matters because version mismatches waste time and cause misleading bugs. Good developers prove the runtime before blaming the application.

Practice

Practice: Prove The Project PHP Version

Create a short version-management checklist for a PHP project.

Task

Include:

  • where to find the required PHP version in composer.json
  • commands to show the active CLI PHP version
  • commands to show all visible PHP binaries
  • a command to check Composer platform requirements
  • a note about checking the web runtime separately from CLI
  • a note about extension availability after switching versions

Include one small PHP web diagnostic snippet that prints PHP_VERSION, PHP_SAPI, and loaded php.ini.

Show solution
{
  "require": {
    "php": "^8.3"
  }
}

Then check the active CLI runtime:

php -v
which php
which -a php
composer check-platform-reqs
php -m

On Windows PowerShell, use:

where php
php -v
composer check-platform-reqs

Temporary web diagnostic:

PHP example
<?php

declare(strict_types=1);

header('Content-Type: text/plain');

echo 'PHP: ' . PHP_VERSION . PHP_EOL;
echo 'SAPI: ' . PHP_SAPI . PHP_EOL;
echo 'Loaded ini: ' . (php_ini_loaded_file() ?: 'none') . PHP_EOL;

CLI checks do not prove the web runtime. PHP-FPM, Apache, Docker, WSL, and local development apps may run a different PHP version or load different extensions. After switching versions, always check extensions again because they are installed and enabled per runtime.