Glossary
Composer
Composer declares, installs, and reproducibly assembles PHP dependencies. It does more than download libraries: it also resolves versions, generates autoloading, and helps deploy the same code predictably.
Short definition
Dependencies are part of the source code even when they do not live in your own repository.
Composer is the tool a PHP project uses to declare libraries, extensions, and supported PHP versions. The composer.json file states what the application needs; Composer then also resolves the indirect dependencies of individual packages. It stores the resulting packages in the vendor directory and makes them available through the generated vendor/autoload.php file.
composer.lock is equally important in an application. It captures the dependency resolver’s specific decisions, including exact versions and package source references. This allows a developer, CI, and the production server to install the same verified set instead of searching on every deployment for the latest versions that merely satisfy an approximate constraint. In a JavaScript project, npm has a comparable role with package.json and a lock file, but it is not a replacement for Composer in PHP.
What it is used for
From frameworks to code quality tools
In a typical PHP project, Composer connects runtime libraries, development tools, and the rules for loading the project’s own code.
- installing a framework, database libraries, and external API clients
- separating production dependencies from tools used only during development and in CI
- PSR-4 autoloading of project code from directories such as src or tests
- running standardised checks and helper commands through Composer scripts
- reproducibly building the same PHP environment for local development, testing, and deployment
Practical example
An importer with clearly defined libraries and its own namespace
The following example deliberately uses a fictional shipping provider client. The principle is what matters: a runtime dependency belongs in require, a testing tool in require-dev, and the project’s own classes have a defined location from which they are loaded automatically. After the declaration changes, a controlled update is performed in the application and the resulting composer.lock is reviewed in the pull request.
A general update is not run in production. Deployment installs the exact versions captured in the lock file, reducing the difference between the environment in which tests passed and the environment in which order imports run.
{
"require": {
"acme/shipping-client": "^2.4"
},
"require-dev": {
"phpunit/phpunit": "^11.0"
},
"autoload": {
"psr-4": { "App\\": "src/" }
}
}
How it works
From a declaration to the same build in every environment
Composer first finds a compatible package graph and then locks it for subsequent installations.
- Declaration composer.json describes required packages, PHP versions, custom autoloading, and any project scripts.
- Version resolution The update command selects versions that satisfy both the project’s constraints and the packages’ mutual dependencies.
- Lock file composer.lock records the exact resolved package set. For a deployed application, it belongs in version control.
- Installation Using the lock file, the install command downloads the exact selected packages into vendor without resolving versions again.
- Autoloading The generated autoloader connects package classes and the project’s own PSR-4 namespaces; the application loads it at its entry point.
Main components and concepts
The declaration, lock, and autoloader have different roles.
Good Composer usage is not about having a vendor directory, but about understanding how it was created.
composer.json
It expresses the project’s intent: direct dependencies, PHP version, autoloading, repositories, and scripts. Versions are constraints, not a record of the environment’s exact state.
composer.lock
It is the concrete result of version resolution. In an application, it is committed and determines the exact package set during installation; manually editing the lock file is risky.
install and update
install installs the locked state. update resolves selected or all dependencies again and can change the lock file, so it requires review and tests.
Autoloading
PSR-4 maps namespaces to directories and avoids manually requiring every class. Composer also supports classmaps and files, but too much automatically loaded code reduces clarity.
Scripts, plugins, and audit
Scripts standardise team commands, but they can execute code during installation. Changes to packages and plugins, and security advisories, therefore belong in normal review.
Benefits and limitations
Reproducibility comes with the cost of regular dependency maintenance.
Benefits
- the same library set in local environments, CI, and deployments
- standardised PSR-4 autoloading of first- and third-party code
- separation of runtime and development tools
- controlled updates with a traceable change in the lock file
Risks and mistakes
- running a broad update without review can introduce many unrelated changes
- an uncommitted lock file gives an application different versions in different environments
- manual vendor changes disappear during the next installation
- adding packages for a small utility increases the supply-chain and operational surface
When it makes sense
Most maintained PHP applications need managed dependencies.
Composer is appropriate as soon as a project uses a framework, API client, or testing tool, or wants to keep its own classes in a predictable namespace. For a long-lived e-commerce site or API, the lock file is one of the practical foundations for reproducible deployments and incident resolution.
There is no need to add a dependency for every line of utility code. A small local function may be clearer when written and tested directly. The decision depends on maintenance, licensing, security updates, compatibility, and whether the package genuinely solves a significant problem better than simple custom code.
Practical guidelines
Update dependencies deliberately, not by accident.
A change to composer.json or composer.lock is a change to the project’s code and deserves the same attention as any other change.
- commit both composer.json and composer.lock for a deployed application
- before production deployment, use install with a verified lock file, not a general update
- when updating, review the changelog, lock file diff, licences, and package maintenance activity
- keep custom PSR-4 namespaces simple and free of conflicting classmap rules
- run tests, static analysis, and security checks after dependency changes
Common questions
What common Composer commands and files mean
What is the difference between composer install and composer update?
install uses versions from composer.lock. update resolves versions again according to the constraints in composer.json and can change the lock file. The former is generally correct for application deployment; updates belong in a controlled change with tests.
Should composer.lock be in version control?
For an application, yes: it describes a specific build that can be reproduced. For a library, the decision differs because its users must resolve dependencies in their own projects.
Does the vendor directory belong in Git?
Usually not. It can be derived from the Composer files and installation. Exceptions may exist in constrained distribution environments, but they must be managed deliberately.
Does Composer handle security by itself?
No. It can help provide an overview of known issues, but a secure process still requires updates, change assessment, tests, and trust in the sources being used.
How I work with PHP in practice
I treat dependencies as part of a maintainable backend.
In PHP applications, I connect frameworks, integration libraries, and quality gates so that changes can be built, tested, and deployed safely.