php runtime and server environment

Installing Extensions

Installing a PHP extension is a runtime task, not an application-code task. The exact command depends on the operating system, PHP installation method, PHP version, and whether the project runs on the host, in Docker, in WSL, or on a server.

The professional workflow is always the same: identify the active runtime, install or enable the extension for that runtime, restart the right process if needed, and verify from the same SAPI that uses it.

Start With The Runtime

Before installing anything, check:

which php
php -v
php --ini
php -m

On Windows PowerShell:

where php
php -v
php --ini
php -m

If the project runs in Docker or WSL, run those checks inside Docker or WSL. Installing an extension on the host will not fix a container runtime.

Linux Packages

On Debian and Ubuntu, extensions are often installed through apt packages with names like:

php-mbstring
php-intl
php-curl
php-zip
php-mysql

On Fedora/RHEL-style systems, names may look like:

php-mbstring
php-intl
php-curl
php-zip
php-mysqlnd

After installing, verify:

php -m | grep mbstring
php --ini

If PHP-FPM is involved, reload or restart the relevant service and verify through the web runtime too.

macOS

On macOS, extensions may come from Homebrew PHP packages, PECL, or a local development app.

Useful checks:

which php
php -v
php --ini
php -m

If a local app manages PHP for you, use that app's extension/version controls and then verify with php -m and a web diagnostic.

Windows

On Windows, many extensions are DLL files. The extension must be enabled in the loaded php.ini, and extension_dir must point to the right folder.

Useful checks:

php --ini
php -i | Select-String "extension_dir"
php -m

Example php.ini lines:

extension=mbstring
extension=pdo_mysql
extension=openssl

If extension_dir is wrong, PHP may not load the DLL even when the file exists.

PECL Extensions

PECL is used for some extensions that are not bundled with PHP or not packaged by the OS in the way you need.

Examples include some Redis, Imagick, and other native extensions depending on platform.

The installation details vary, but verification stays the same:

php -m
php --ri redis
php --ri imagick

php --ri extension_name shows information about a loaded extension. If the extension is not loaded, it reports that it is not present.

Docker Images

In Docker, extensions should be installed in the image, not manually inside a running container.

Example shape:

FROM php:8.3-fpm

RUN docker-php-ext-install pdo_mysql

Then rebuild and verify inside the container:

php -m
composer check-platform-reqs

Manual changes inside a running container disappear when the container is rebuilt.

Enabling Versus Installing

An extension can be installed but not enabled.

Check loaded extensions:

php -m

Check configuration files:

php --ini

Look for .ini files that contain lines such as:

extension=intl
zend_extension=opcache

Use zend_extension for Zend engine extensions such as OPcache and Xdebug.

Verify With PHP Code

Use a small diagnostic when debugging a project:

PHP example
<?php

declare(strict_types=1);

if (PHP_SAPI !== 'cli') {
    header('Content-Type: text/plain');
}

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

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

Run it in CLI and through the web server if the problem appears only in the browser.

Composer Platform Requirements

After installing extensions, run:

composer check-platform-reqs

This checks the current PHP runtime against the project's composer.json requirements.

If a required extension is missing, fix the runtime or container image. Do not remove ext-* requirements just to make Composer pass unless the project genuinely no longer needs that extension.

What You Should Be Able To Do

After this lesson, you should be able to identify the active runtime, install or enable extensions through the correct platform mechanism, distinguish installed from loaded, restart the right process, and verify extension availability through CLI, web diagnostics, and Composer.

For junior PHP work, this matters because extension problems are setup problems. The correct fix is usually in the runtime, not in the application code.

Practice

Practice: Plan An Extension Install

Create a checklist for installing a missing PHP extension.

Task

Choose intl, pdo_mysql, or redis and write a plan that includes:

  • how to prove which PHP runtime is active
  • how to check whether the extension is already loaded
  • where you would install or enable it for Linux, Windows, or Docker
  • which process may need a restart
  • how to verify the extension from PHP code
  • how to verify Composer platform requirements

Use strict types for the PHP diagnostic snippet. Keep example output inside the PHP code block as comments.

Show solution
which php
php -v
php --ini
php -m | grep intl

On Windows PowerShell:

where php
php -v
php --ini
php -m | Select-String intl

For Linux packages, install the matching package for the active PHP version and distribution. For Windows, enable the extension in the loaded php.ini and confirm extension_dir points at the DLL folder. For Docker, add the install step to the Dockerfile and rebuild the image.

PHP diagnostic:

PHP example
<?php

declare(strict_types=1);

if (PHP_SAPI !== 'cli') {
    header('Content-Type: text/plain');
}

echo 'SAPI: ' . PHP_SAPI . PHP_EOL;
echo 'Loaded ini: ' . (php_ini_loaded_file() ?: 'none') . PHP_EOL;
echo 'intl: ' . (extension_loaded('intl') ? 'loaded' : 'missing') . PHP_EOL;

// Prints:
// SAPI: cli
// Loaded ini: /etc/php.ini
// intl: loaded

If PHP-FPM or another web runtime uses the extension, reload or restart that process after enabling it. Finish by running:

composer check-platform-reqs

That proves the active runtime satisfies the project's declared extension requirements.