Best Practices

This page is a capstone checklist for the whole Composer track — the habits worth carrying into every real project. Each item links back to the page that covers it in full, so use this as a quick-reference summary rather than a first read.

1) Commit composer.lock for Applications

If you're building an application — something that gets deployed and run, not installed as a dependency by other projects — commit composer.lock to version control. It's what guarantees every teammate and every server installs the exact same package versions. Standalone libraries meant to be installed inside other people's projects are the exception: they typically don't commit their lock file, since the consuming project's own constraints decide the final versions. See The composer.lock File.

git add composer.lock
git commit -m "Update locked dependency versions"
  • Commit composer.lock for any application you deploy.
  • Skip committing it for a reusable library published for other projects to install.

2) Install in CI/CD, Update Deliberately and Locally

Deployment pipelines and production servers should almost always run composer install, which respects the exact versions in composer.lock. Save composer update for your own machine, where you can test the result before committing the new lock file. See Update vs Install.

# In CI/CD and on production servers
composer install --no-interaction

# On your own machine, when you want newer versions
composer update
  • Use composer install everywhere dependencies just need to be reproduced exactly.
  • Reach for composer update only when you deliberately want newer versions, and test locally first.

3) Keep Dev-Only Tools in require-dev

Testing frameworks, debuggers, and style checkers belong under require-dev, not require. Deploy with --no-dev so none of that tooling ships to production. See Dev Dependencies.

composer require --dev phpunit/phpunit
composer install --no-dev
  • Put testing and debugging tools under require-dev, never require.
  • Always deploy with composer install --no-dev to keep production lean.

4) Pin Sensible Version Constraints

A version constraint like "^3.0" allows compatible updates while still protecting you from an unexpected major version jump. An unconstrained "*" tells Composer "any version at all is fine," which invites a breaking change to slip in the next time anyone runs composer update.

{
    "require": {
        // Good: allows compatible updates, blocks breaking major versions
        "monolog/monolog": "^3.0",

        // Risky: accepts literally any version, including breaking ones
        "some/package": "*"
    }
}
  • Prefer caret (^) constraints over a bare * wildcard.
  • Review a package's changelog before loosening a constraint on purpose.

5) Optimize the Autoloader for Production

Composer's default autoloader looks packages up dynamically. The -o (optimize) flag generates a static class map instead, which is faster to resolve on every request — a small but real performance boost worth having in production.

composer dump-autoload -o
  • Run composer dump-autoload -o (or composer install -o) as part of your production deploy.
  • Skip the optimize flag locally, where the small dynamic-lookup cost doesn't matter and you want autoloading to stay flexible while developing.

6) Never Commit the vendor/ Folder

vendor/ is entirely regenerated from composer.json and composer.lock — committing it bloats your repository with files that don't belong there and can drift out of sync with the lock file. Add it to .gitignore and let composer install rebuild it wherever the code runs.

vendor/
  • Add vendor/ to .gitignore in every Composer-managed project.
  • Trust composer install to rebuild it identically on any machine, using composer.lock.

7) Map Your Own Classes with PSR-4, Not Manual require

Once your project has more than a couple of files, scattering manual require statements through the codebase becomes a maintenance headache. Let Composer's autoload section and PSR-4 handle it, and remember to run composer dump-autoload after changing that section. See Autoloading Your Own Code.

{
    "autoload": {
        "psr-4": {
            "App\\": "src/"
        }
    }
}
  • Map your own namespaces under PSR-4 instead of writing manual include/require chains.
  • Run composer dump-autoload any time you change the autoload section by hand.
Quick recap:
PracticeCovered in
Commit composer.lock for applicationsThe composer.lock File
Install in CI/CD, update deliberatelyUpdate vs Install
Keep dev tools out of productionDev Dependencies
Avoid loose * version constraintsThis page
Optimize the autoloader for productionThis page
Never commit vendor/This page
PSR-4 map your own classesAutoloading Your Own Code
You've completed the Composer track! Congratulations on working through everything from your first composer.json to autoloading, lock files, dev dependencies, your own PSR-4 classes, scripts, and global tools. This same dependency-management discipline carries straight into every PHP framework track on this site — Laravel, Symfony, and CodeIgniter (all coming soon) are all built on top of Composer, so everything you've learned here keeps paying off. Click Next below to head back to the PHP hub and pick another track to continue learning.