Lock PHP Versions Across Environments with Composer’s config.platform
When your team’s PHP versions drift, dependency resolution can break. Composer’s `config.platform` lets you emulate a specific PHP runtime during installs, ensuring the same lockfile everywhere. Learn how to set it up, what it does, and its trade‑offs.
17 Feb 2026, 22:44 UTC

Why PHP Version Drift Matters
In a typical PHP project, each developer’s machine, the staging server, and the production host often run different PHP releases. Even a minor difference can cause a package that requires php >= 8.0 to be installed locally but omitted on a host running PHP 7.4. The result is a lockfile that looks good in one place but fails silently or throws runtime errors in another.
Thesis: Composer’s config.platform Emulates a Target PHP Runtime
The config.platform key in composer.json tells Composer to pretend that the PHP interpreter it’s running on matches the version you specify. During dependency resolution, Composer treats that version as the host, ignoring the actual runtime. This yields a lockfile that is reproducible across all environments that share the same config.platform setting.
Section 1 – What Is config.platform?
- Defined under
configincomposer.jsonor set via the CLI. - Only affects the resolution phase of Composer; it does not change the PHP interpreter you run your code with.
- Typical syntax:
{ "config": { "platform": { "php": "7.4" } } }.
Section 2 – Why Use It?
- Reproducible lockfiles – every machine sees the same set of packages.
- Prevents accidental installation of packages that require a newer PHP version than your target environment.
- Helps teams lock the environment before pushing to CI or production.
Worked Example
Suppose your production server runs PHP 7.4, but your local machine is on PHP 8.1. You want all developers and CI to install dependencies as if they were on 7.4.
- Open
composer.jsonand add the platform key:{ "require": { "symfony/console": "^5.4" }, "config": { "platform": { "php": "7.4" } } } - Run
composer updatelocally. Composer will resolve dependencies as if PHP 7.4 is running, even though the CLI is PHP 8.1.composer update - Commit the updated
composer.lockto version control. - In your CI pipeline, ensure the same
config.platformis present (or set the environment variableCOMPOSER_PLATFORM_PHP=7.4) before runningcomposer install.
Result: The lockfile contains packages compatible with PHP 7.4, and all environments install the same set.
Trade‑Offs and Limitations
- The setting only influences Composer’s dependency resolution; it does not downgrade or upgrade the actual PHP interpreter used at runtime.
- Running the application on a newer PHP (e.g., 8.1) can still expose API changes if your code or dependencies rely on features removed in 7.4.
- Setting a lower PHP version may silently exclude packages that truly need a newer PHP, potentially breaking functionality that only manifests under certain conditions.
- Composer 1.x is End‑of‑Life;
config.platformis guaranteed only in Composer 2.x and above. - Keep the
config.platformentry under version control so every team member and CI job uses the same constraints.
Actionable Checklist
- Add
config.platform.phptocomposer.jsonwith your target PHP version. - Run
composer updatelocally and commit the lockfile. - Configure your CI environment to use the same
composer.json(or exportCOMPOSER_PLATFORM_PHP). - Test the application on the highest PHP version you expect to run on production to catch any API mismatches early.
- Document the platform configuration in your project README so new contributors understand the enforced PHP version.
Conclusion
Composer’s config.platform is a lightweight, declarative way to enforce a consistent PHP runtime across all stages of your workflow. By pinning the platform version, you eliminate the “works on my machine” syndrome caused by PHP version drift, while still allowing your code to run on newer interpreters when appropriate. Add it to your composer.json, update, and test – your dependency graph stays stable, and your team stays productive.
0 replies
A thoughtful contribution can make all the difference. Be the first to share one.