In short: Composer is the package manager for PHP. From the file composer.json it reads which libraries a project needs, downloads them into the vendor folder, records the exact versions in composer.lock and generates an autoloader that finds classes automatically. Composer thus manages your application's code, not the PHP interpreter itself: a Composer update does not close a flaw in PHP such as PHP2Shell.
What is Composer and what is it needed for?
Hardly any PHP application today consists of its own code alone. Frameworks, mail libraries, PDF generation or payment integrations are added as ready-made packages. Composer, the package manager for PHP, ensures that these packages come together in matching versions and that every dependency brings along its own dependencies.
For decision-makers this means: a large part of the code running on your server comes from third parties. That is efficient but needs maintenance. For admins and developers it means: anyone who uses Composer cleanly can trace at any time which version of which library is running in production.
According to the Composer documentation, the default source for packages is Packagist.org. Other sources, such as an agency's internal repositories, can be entered in composer.json under repositories.
composer.json, composer.lock and vendor: the three building blocks
Composer works with three things that you should know before taking over a server or commissioning an agency.
| Building block | Content | Belongs in the repository? |
|---|---|---|
composer.json |
desired packages with version ranges (require, require-dev), autoload rules, settings |
yes |
composer.lock |
exactly resolved versions of all packages, including indirect ones | yes, explicitly according to the Composer docs |
vendor/ |
downloaded code of the packages and the generated autoloader | no, it is generated during installation |
Under require are packages the application needs in operation. Under require-dev are tools for development and testing, such as test frameworks or static analysis. This separation is important because development tools have no place on a production server.
{
"require": {
"php": ">=8.3",
"monolog/monolog": "^3.0"
},
"require-dev": {
"phpunit/phpunit": "^11.0"
},
"autoload": {
"psr-4": { "App\\": "src/" }
}
}
The version numbers in the example are chosen for illustration only. Which versions your project needs follows from its requirements.
install or update: the difference in operation
The two commands sound similar but have very different consequences.
composer installreadscomposer.lockand installs exactly the versions recorded there. This is reproducible and belongs in deployment.composer updateresolves all dependencies anew, fetches the latest matching versions and rewritescomposer.lock. This belongs in development, followed by tests.
According to the Composer documentation, after writing the lock file update additionally runs a security check (audit), unless it is switched off with --no-audit. install does not check by default; the option --audit exists for that.
Autoloading: how Composer finds classes
Composer generates the file vendor/autoload.php. Once it is included, PHP loads each class only when it is needed. For your own code, the autoload section defines which namespace lives in which folder. PSR-4, a PHP-FIG standard, is recommended for this. Exactly how this works is explained on the page Namespaces and autoloading; an overview of all standards is given on the page PSR standards.
<?php
require __DIR__ . '/../vendor/autoload.php';
$log = new Monolog\Logger('app'); // loaded automatically when needed
Composer in production: deploying cleanly
A fixed sequence has proven itself for deployment. It runs best in a build pipeline and not by hand on the server.
- Check the lock file:
composer validateensures thatcomposer.jsonis valid andcomposer.lockis up to date. - Install without development packages:
composer install --no-devleaves outrequire-dev. - Optimise the autoloader:
--optimize-autoloader(short-o) converts the rules into a class list. With--classmap-authoritative, PHP loads classes exclusively from this list. - Security check:
composer audit --lockedchecks the versions from the lock file against known security advisories and reports abandoned packages. - vendor outside the web root: Only the public folder with the entry script should be reachable via URL.
composer validate
composer install --no-dev --optimize-autoloader
composer audit --locked --no-dev
composer outdated additionally shows which installed packages have newer versions. This is the basis for planned updates instead of hectic one-off actions.
Composer, security and PHP2Shell
Composer and PHP2Shell concern two different levels. The flaws CVE-2026-109618 and CVE-2026-109619 lie in the PHP interpreter itself. They are fixed in PHP 8.5.12, 8.4.27, 8.3.36 and 8.2.35, and all PHP processes must be restarted afterwards. No composer update and no package in vendor changes that.
Even so, Composer belongs in every check after an incident. Anyone who brings malicious code onto a server can also change files in vendor, and vendor/autoload.php is loaded on every request. A fresh composer install from the verified lock file into an empty directory is therefore a good way to restore the package inventory. How to check dependencies regularly for known flaws is described in the guide composer audit.
A green composer audit says nothing about PHP's patch level. Check the PHP runtime separately, for example with our PHP patch service.
How does PHP SOS help?
- For each application we record the PHP version, Composer packages and lock state, cleanly separating the interpreter from the libraries.
- We check whether
vendorand the lock file match each other and whether development packages or altered files are present in production. - We set up reproducible deployment with
install --no-dev, an optimised autoloader and audit. - After an incident we rebuild the package inventory from the verified lock file and document the result.
Frequently asked questions
Does composer.lock have to go into the Git repository?
Yes. The Composer documentation explicitly recommends committing composer.lock. Only then do development, CI and production install exactly the same package versions.
What is the difference between composer install and composer update?
install installs the versions recorded in composer.lock. update resolves the dependencies anew, fetches suitable newer versions and rewrites composer.lock. On the production server only install belongs.
Does a Composer update close the PHP2Shell flaw?
No. Composer manages your application's libraries, not the PHP interpreter. PHP2Shell is closed only by updating the PHP runtime to a fixed version and restarting all PHP processes.
Where should the vendor folder be located?
Ideally outside the publicly accessible web directory. Many frameworks place only a public folder in the web root, while vendor sits one level above.