Question

How to Install a Specific Package Version with Composer in PHP

phpcomposer-phpdependency-management

Question

I want to install a specific version of a package using Composer in a PHP project. When I run commands like composer install or composer require, Composer installs the latest compatible version. How can I install an older or exact version of a package instead?

Short Answer

By the end of this page, you will understand how Composer version constraints work, how to require an exact or older package version, and how to verify that the correct version was installed. You will also learn the difference between composer install and composer require, common mistakes, and how this is handled in real PHP projects.

Concept

Composer uses version constraints to decide which package version it should install. When you ask Composer to add a package without specifying a version, it usually chooses the latest version that is compatible with your project settings and dependency rules.

If you want an older version, you must tell Composer which version or version range you want.

For example:

composer require vendor/package:1.2.3

This tells Composer to install version 1.2.3 of that package, if it is available and compatible with the rest of your dependencies.

This matters because in real projects:

  • a newer package version may break old code
  • a package version may require a newer PHP version than your project uses
  • your team may want consistent dependency versions across environments
  • a tutorial or legacy codebase may depend on a specific release

Composer does not just install packages randomly. It resolves a full dependency graph. That means even if you request a version, Composer still checks whether that version can work with:

  • your PHP version
  • your existing dependencies
  • the package's own sub-dependencies

If there is a conflict, Composer will refuse the installation and show an error.

Mental Model

Think of Composer like a librarian finding books for a reading list.

  • composer require vendor/package means: "Give me this book, latest suitable edition."
  • composer require vendor/package:1.2.3 means: "Give me exactly the 1.2.3 edition."
  • composer install means: "Use the reading list exactly as already recorded in the lock file."
  • composer update means: "Check if newer allowed editions are available and refresh the list."

So if you want a specific edition, you must write that edition into the request. Otherwise, Composer tries to find the newest version that fits the rules.

Take Quiz

Syntax and Examples

The most common way to install a specific version is:

composer require vendor/package:1.2.3

Exact version

composer require monolog/monolog:2.9.1

This adds the package and updates composer.json with that version constraint.

Install a major version line

composer require monolog/monolog:^2.0

This means:

  • allow version 2.0 or higher
  • but not 3.0 or above

Composer will install the latest available 2.x version.

Install an older minor version range

composer require monolog/monolog:^1.0

This is useful when a project is built for version 1 of a package and is not yet compatible with version 2 or 3.

Edit composer.json manually

You can also write the dependency yourself:

{
  "require": {
    "monolog/monolog": "2.9.1"
  }
}

Then run:

composer update monolog/monolog

This tells Composer to resolve and install that package according to the version you specified.

Check installed version

composer show monolog/monolog

This displays information about the installed package version.

Important note about composer install

composer install

This command does not choose a new version from scratch if composer.lock already exists. It installs the versions already locked in that file.

Step by Step Execution

Consider this command:

composer require monolog/monolog:2.9.1

Here is what happens step by step:

  1. Composer reads your composer.json file.
  2. It adds monolog/monolog with the constraint 2.9.1 to the require section.
  3. It checks Packagist or configured repositories for that exact version.
  4. It checks whether version 2.9.1 is compatible with:
    • your PHP version
    • your other installed packages
    • the package's dependencies
  5. If everything is compatible, Composer downloads the package.
  6. Composer writes the resolved versions to composer.lock.
  7. The package files are placed in the vendor/ directory.

Example trace:

composer require monolog/monolog:2.9.1

Possible result in composer.json:

{
  "require": {
    "monolog/monolog": "2.9.1"
  }
}

Then if you run:

composer install

Composer reads composer.lock and installs the exact locked version again, instead of searching for a newer one.

Real World Use Cases

Installing a specific package version is common in real PHP work.

Maintaining legacy applications

Older Laravel, Symfony, or custom PHP projects may only work with certain package versions.

Following a tutorial or course

A tutorial may use an older package API. Installing the same version helps your code match the lesson.

Avoiding breaking changes

A new major release may change method names, configuration, or behavior. Pinning a version prevents accidental breakage.

Meeting PHP version limits

Some package releases require newer PHP versions. If your server runs an older PHP version, you may need an older package release.

Reproducing bugs

When debugging, developers sometimes install the exact version where a bug was reported so they can reproduce it reliably.

Take Quiz

Real Codebase Usage

In real projects, developers usually do more than just install a package.

Common patterns

Pinning exact versions for stability

Teams may use exact versions like:

"vendor/package": "1.4.2"

This gives predictable builds.

Using semantic version constraints

Many projects prefer flexible but controlled constraints:

"vendor/package": "^1.4"

This allows safe updates within the same major version.

Locking with composer.lock

A team commits composer.lock so every developer and deployment server installs the same resolved versions.

Updating one package at a time

Instead of updating everything, developers often run:

composer update vendor/package

This reduces risk.

Checking compatibility before upgrading

Developers read changelogs and package requirements before moving from one major version to another.

Using guardrails in CI

Automated tests often catch problems caused by dependency version changes. This is one reason version control in Composer matters so much.

Common Mistakes

Using composer install when you mean composer require

Broken idea:

composer install monolog/monolog:2.9.1

Why it is wrong:

  • composer install installs from composer.lock
  • it does not add a new package with a version constraint like this

Use instead:

composer require monolog/monolog:2.9.1

Forgetting the version after the package name

composer require monolog/monolog

This usually installs the latest compatible version, not necessarily the old one you wanted.

Confusing exact versions with ranges

composer require monolog/monolog:^2.0

This does not mean exactly 2.0.0. It means any compatible 2.x version.

If you want an exact version, use:

composer require monolog/monolog:2.0.0

Editing composer.json but forgetting to update

If you manually change composer.json, you usually need:

composer update vendor/package

Otherwise the installed version may remain unchanged.

Ignoring dependency conflicts

Sometimes the version you want cannot be installed because another package needs a different version. Composer will show a solver error. Read that message carefully instead of forcing random changes.

Not checking the installed version

After requiring a package, confirm it:

composer show vendor/package

Comparisons

Command or ConstraintWhat it doesTypical use
composer require vendor/packageAdds the package using the latest compatible versionNormal package installation
composer require vendor/package:1.2.3Installs an exact versionReproducing old setups or avoiding breaking changes
composer installInstalls versions from composer.lockTeam setup, CI, deployment
composer updateRe-resolves versions based on constraintsRefreshing dependencies
1.2.3Exact version onlyMaximum stability
^1.2Any compatible version within major version 1Safe upgrades within one major line
~1.2Usually allows patch/minor updates within a narrower rangeMore controlled updates

install vs require vs update

  • require: add a dependency and set its version constraint
  • install: install exactly what is in composer.lock
  • update: recalculate allowed versions and refresh the lock file

Exact version vs version constraint

  • Exact version: best when you need full consistency
  • Constraint like ^2.0: best when you want updates without crossing into a breaking major release
Take Quiz

Cheat Sheet

# Install an exact version
composer require vendor/package:1.2.3

# Install latest compatible version in major version 2
composer require vendor/package:^2.0

# Install from lock file
composer install

# Update only one package after editing composer.json
composer update vendor/package

# Show installed package info
composer show vendor/package

Rules to remember

  • composer require adds a package
  • composer install uses composer.lock
  • composer update recalculates versions
  • 1.2.3 means exact version
  • ^2.0 means any compatible 2.x version
  • If composer.lock exists, install follows it exactly

Edge cases

  • The version you want may not exist
  • The version may conflict with PHP or other dependencies
  • An exact version in composer.json still depends on dependency resolution succeeding

FAQ

How do I install an exact version of a package in Composer?

Use:

composer require vendor/package:1.2.3

Replace the package name and version with the ones you need.

Why does Composer install a newer version than I expected?

If you do not specify an exact version, Composer follows the version constraint rules and usually picks the latest compatible release.

What is the difference between composer install and composer require?

composer require adds a package and version constraint. composer install installs versions already recorded in composer.lock.

Can I install an older package version after already installing a newer one?

Yes. Run composer require vendor/package:desired-version or change composer.json and then update that package.

How can I see which version was installed?

Run:

composer show vendor/package

What if Composer says the requested version cannot be installed?

Usually there is a dependency conflict, PHP version mismatch, or the version does not exist. Read the solver error carefully.

Should I use exact versions in production projects?

It depends. Exact versions give stability, while constraints like ^1.2 allow safer updates. Many teams rely on composer.lock for consistent installs.

Take Quiz

Mini Project

Description

Create a small PHP project that installs a logger package using a specific Composer version. This demonstrates how version constraints affect installation and how to verify the installed result.

Goal

Install a package at a chosen version, verify it, and understand which Composer files changed.

Requirements

  • Create a new PHP project folder with Composer initialized
  • Install a package using an exact version number
  • Verify the installed package version with a Composer command
  • Inspect the changes in composer.json and composer.lock
  • Run a simple PHP file that loads Composer autoloading
Take Quiz

Keep learning

Related questions

View more