A PHP application can work perfectly on a developer's machine and still fail after deployment. One common reason is a mismatch between the PHP environment used during development and the environment running the application in production.
For example, a developer might use PHP 8.4 while the production server runs PHP 8.2. A dependency may require a newer PHP version, or an application may rely on an extension such as ext-intl or ext-redis that is missing from the production environment.
Composer provides platform configuration and validation commands to help identify these problems before deployment. These features allow developers to define the platform used during dependency resolution and verify whether the actual PHP environment satisfies the application's requirements.
This article explains how Composer platform configuration works, how to detect PHP version mismatches, and how to incorporate platform checks into a deployment workflow.
Understanding Composer Platform Requirements
Composer manages PHP packages and resolves their dependencies. During dependency resolution, it considers more than package names and version constraints. It also checks platform requirements, including the PHP version and required PHP extensions.
For example, a package might declare the following requirements in its composer.json file:
{
"require": {
"php": "^8.3",
"ext-json": "*",
"ext-mbstring": "*"
}
}
This configuration indicates that the package requires a compatible PHP 8.3 release and the json and mbstring extensions.
If the production environment runs PHP 8.2, the application may not be installable with these requirements. Even if the dependency installation succeeds in a different environment, the production runtime must still satisfy the actual requirements.
Composer represents PHP itself and its extensions as platform packages. Common examples include:
Platform package | Purpose |
|---|
php | Represents the PHP runtime version |
ext-json | Represents the JSON extension |
ext-mbstring | Represents the Multibyte String extension |
ext-intl | Represents the Internationalization extension |
ext-curl | Represents the cURL extension |
ext-pdo | Represents the PDO database access extension |
lib-* | Represents supported system libraries where applicable |
These requirements help prevent incompatible dependencies from being installed without warning.
Configuring the Target PHP Version
One useful Composer feature is config.platform. It allows a project to specify the PHP platform version that Composer should use when resolving dependencies.
Suppose developers use different PHP versions, but production runs PHP 8.3. The project can configure Composer to resolve dependencies against PHP 8.3.
Add the following configuration to composer.json:
{
"config": {
"platform": {
"php": "8.3.0"
}
}
}
This tells Composer to simulate PHP 8.3.0 for dependency resolution.
You can also set the configuration through the command line:
composer config platform.php 8.3.0
The command updates the project's Composer configuration.
What Does Platform Simulation Mean?
The platform.php setting influences which dependency versions Composer considers compatible. It does not change the PHP version installed on the developer's machine or production server.
For example, suppose a developer uses PHP 8.4 while the project targets PHP 8.3. With the platform setting configured, Composer resolves dependencies as though PHP 8.3.0 were the target platform.
This helps prevent the dependency resolver from selecting packages that require PHP 8.4 when the project must support PHP 8.3.
However, platform simulation has a limitation: it does not guarantee that the application will behave correctly on PHP 8.3. Developers should still test the application using the actual target PHP version.
The configured platform version should reflect the oldest PHP version the application promises to support, or the specific runtime version required by the deployment environment.
Why Composer Platform Configuration Is Not Enough
A common mistake is assuming that configuring platform.php guarantees compatibility with the real production environment.
Consider this configuration:
{
"config": {
"platform": {
"php": "8.3.0",
"ext-intl": "1.0"
}
}
}
Composer can use these values when resolving dependencies. However, the extension declaration simulates the presence of ext-intl; it does not install the extension.
If the actual production PHP runtime does not have the Internationalization extension installed, the application can still fail.
The same principle applies to other platform packages. Simulating a platform requirement can be useful when resolving dependencies, but it must not be confused with verifying the actual environment.
To catch this difference, use Composer's check-platform-reqs command.
Checking the Actual PHP Environment
Composer provides a command that verifies whether the real PHP environment satisfies the platform requirements of the project.
Run:
composer check-platform-reqs
Unlike dependency resolution based on config.platform, this command checks the actual platform rather than the simulated platform configuration.
This makes it useful for detecting missing extensions and PHP version mismatches.
For example, suppose composer.json simulates PHP 8.3, but the production server actually runs PHP 8.2. If the installed dependencies require PHP 8.3, the platform check can report that the actual runtime does not satisfy the requirement.
For a production deployment that excludes development dependencies, run:
composer check-platform-reqs --no-dev
This checks the platform requirements of the installed production dependency set without requiring development dependencies.
The command should run in the same environment that will execute the application. Checking PHP on a developer's laptop does not verify the PHP installation inside a production container or on a remote server.
Verifying PHP and Extension Requirements
Before deploying an application, verify the PHP version:
php -v
To inspect the extensions loaded by the command-line PHP installation, run:
php -m
You can also inspect the configuration used by the CLI:
php --ini
These commands are useful because PHP installations can differ between environments. For example, the command-line PHP executable may use a different configuration from PHP-FPM.
If a deployment uses PHP-FPM, a container, or another execution environment, ensure that the checks run against the runtime that actually serves the application.
For an application requiring the intl extension, you can declare the requirement in composer.json:
{
"require": {
"php": "^8.3",
"ext-intl": "*"
}
}
This declaration allows Composer to consider the extension during dependency resolution and platform validation.
The wildcard means that Composer does not enforce a specific extension version through this requirement. It does not mean the extension is optional.
If the extension is missing, install and enable it in the target environment rather than attempting to bypass the platform check.
Enabling Composer's Platform Check
Composer can generate a platform-check file that verifies certain runtime requirements when Composer's generated autoloader is loaded.
Configure it explicitly in composer.json:
{
"config": {
"platform-check": true
}
}
With this setting, Composer generates runtime checks for the supported PHP and extension requirements represented by its platform-check mechanism.
The platform-check configuration also supports "php-only" in Composer versions that provide this option. That setting limits the generated check to the PHP version rather than checking extensions.
For most applications, checking the required extensions is valuable because an extension can be present in the dependency metadata but absent from the actual runtime.
However, a generated platform check is not a replacement for deployment validation. It only checks the requirements covered by Composer's mechanism, and some problems may not become apparent until the application executes a particular code path.
Keep platform-check enabled unless there is a documented reason to change it.
Using Composer Commands in a Deployment Workflow
A reliable deployment process should validate dependency configuration, install the locked dependencies, and check the real runtime.
The following sequence provides a practical starting point:
composer validate --strict
composer install --no-dev --prefer-dist --optimize-autoloader
composer check-platform-reqs --no-dev
Each command serves a different purpose.
Command | Purpose |
|---|
composer validate --strict | Validates the Composer configuration and lock-file consistency, with strict validation rules |
composer install --no-dev --prefer-dist --optimize-autoloader | Installs the locked production dependencies and optimizes the autoloader |
composer check-platform-reqs --no-dev | Checks the actual PHP environment against the production dependency requirements |
Run these commands in the appropriate deployment environment. If dependency installation happens in a build container but the application runs in a different production container, checking the build container alone is insufficient.
For reproducible deployments, commit composer.lock to version control for applications. The lock file records the resolved package versions, reducing the chance that different environments install different dependency versions.
Do not replace composer install with composer update during a routine production deployment. The update command resolves dependencies again and may change package versions.
Adding Platform Checks to CI/CD
You can run platform validation in a continuous integration pipeline before releasing an application.
For example, a simplified shell step could look like this:
set -e
composer validate --strict
composer install --no-interaction --prefer-dist
composer check-platform-reqs
The set -e statement causes the shell script to stop when a command fails, preventing later steps from continuing after a failed validation.
For a production deployment job, use the same PHP version and required extensions as the production runtime. If your CI environment intentionally includes development tools or additional extensions, consider adding a separate validation job that reproduces the production environment more closely.
This approach catches several problems before release:
A dependency requires a newer PHP version than production provides.
A required extension is missing.
The Composer configuration is invalid.
The lock file is inconsistent with the dependency declarations.
The deployment environment differs from the environment used to resolve dependencies.
A successful platform check does not guarantee that every application feature works, so combine it with automated tests and appropriate integration tests.
Common Mistakes to Avoid
Mistake | Why it causes problems | Better approach |
|---|
Assuming platform.php changes the installed PHP version | It affects dependency resolution, not the actual runtime | Install and test the required PHP version |
Simulating an extension that is not installed | Dependencies may resolve despite a missing runtime extension | Run composer check-platform-reqs in the target environment |
Running checks only on a developer's machine | Production may have a different PHP configuration | Validate the deployment runtime |
Running composer update during every deployment | Dependency versions can change unexpectedly | Commit and install composer.lock |
Disabling platform checks to hide failures | The application may deploy with incompatible requirements | Fix the PHP version or install the required extension |
Assuming a successful platform check proves the application works | Runtime behavior and business logic are not fully validated | Combine platform checks with automated tests |
Advantages and Disadvantages
Composer platform configuration provides several benefits:
It lets teams resolve dependencies against a defined PHP version.
It reduces accidental dependency upgrades beyond the supported runtime.
It helps identify missing PHP extensions before deployment.
It supports more consistent dependency installation across environments.
It integrates easily into CI/CD pipelines.
There are also limitations. Simulated platform configuration can create a false sense of security if the actual runtime is not checked. Extension availability may differ across containers and servers, and platform checks cannot replace application testing.
The best results come from combining a clearly defined target platform, a committed lock file, actual runtime validation, and automated tests.
Summary
Composer platform configuration helps PHP teams control which dependency versions are considered compatible with their target environment. Setting config.platform.php makes dependency resolution more predictable, but it does not install or emulate the actual runtime for application execution.
Use composer check-platform-reqs to verify the real PHP version and required extensions. Keep composer.lock under version control, run validation in CI/CD, and ensure that checks use an environment representative of production.
These practices help identify PHP version mismatches and missing extensions before deployment, reducing avoidable release failures.
Join the conversation! Your thoughts help the community grow.