Skip to content

PHP Composer — Complete Guide to Dependency Management

DodaTech Updated 2026-06-28 6 min read

In this tutorial, you will learn about PHP Composer. We cover key concepts, practical examples, and best practices to help you master this topic.

PHP Composer is the industry-standard dependency manager for PHP that installs, updates, and autoloads third-party libraries and packages into your projects. This tutorial walks you through installing Composer, understanding composer.json and composer.lock, requiring and updating packages, leveraging PSR-4 autoloading for your own code, creating and publishing packages, and following semantic versioning for reliable dependency resolution.

What You'll Learn

  • Installing Composer globally and understanding the composer.json schema
  • Requiring, updating, and removing packages with version constraints
  • Understanding the difference between composer.json and composer.lock
  • Configuring PSR-4 autoloading for your own source code
  • Creating a custom package and publishing it to Packagist
  • Using scripts hooks for automated build steps

Why It Matters

Before Composer, PHP developers copied library files manually, leading to version conflicts, abandoned updates, and security vulnerabilities. Composer solves these problems with a single command: composer require. It resolves dependency versions mathematically, generates an optimized autoloader, and ensures every developer on your team uses identical library versions. This is how modern PHP projects, from Laravel to Symfony to Drupal, manage their dependencies.

Real-World Use

DodaZIP, the compression tool suite, depends on 12 Composer packages for encryption, file format detection, and cloud storage integration. Composer's lock file ensures that every build, whether on a developer laptop or a CI server, uses the exact same library versions. When a security patch is released for one dependency, a single composer update propagates the fix across the entire application.

Learning Path

flowchart LR
  A[Debugging] --> B[Composer\nYou are here]
  B --> C[PSR Standards]
  style B fill:#f90,color:#fff

Installing Composer

Download and install Composer globally:

php -r "copy('https://getcomposer.org/installer', 'composer-setup.php');"
php composer-setup.php --install-dir=/usr/local/bin --filename=composer
php -r "unlink('composer-setup.php');"

Verify the installation:

composer --version

Output:

Composer version 2.8.0 2026-05-15 14:08:33

Creating a composer.json

Every project begins with a composer.json file. Create one with composer init:

composer init --name="myapp/demo" --type="project" --description="A demo project" --no-interaction

This generates:

{
  "name": "myapp/demo",
  "description": "A demo project",
  "type": "project",
  "require": {}
}

The name field uses the format vendor/package. Composer uses this to identify your project and its packages.

Requiring Packages

Add a package with composer require:

composer require monolog/monolog

This command downloads the monolog/monolog package with the best compatible version, updates composer.json, and generates composer.lock. The lock file records the exact version of every installed package:

{
  "require": {
    "monolog/monolog": "^3.0"
  }
}

Use the package in your code:

<?php
require __DIR__ . '/vendor/autoload.php';

use Monolog\Logger;
use Monolog\Handler\StreamHandler;

$logger = new Logger('app');
$logger->pushHandler(new StreamHandler(__DIR__ . '/app.log', Logger::WARNING));
$logger->warning('This is a warning message');
$logger->error('This is an error message');

Output (file app.log):

[2026-06-28T12:00:00.000000+00:00] app.WARNING: This is a warning message []
[2026-06-28T12:00:01.000000+00:00] app.ERROR: This is an error message []

Understanding Version Constraints

Composer supports several version constraint formats:

Constraint Meaning
^3.0 Compatible with 3.0 up to 4.0 (exclusive)
~3.0 Compatible with 3.0 up to 3.9999
>=3.0 <4.0 Explicit range
3.0.* Any 3.0.x version
dev-main Development branch (add "minimum-stability": "dev")

Run composer update to upgrade all packages within their constraints:

composer update

Configuring PSR-4 Autoloading for Your Code

Composer can autoload your own classes. Add the autoload section to composer.json:

{
  "name": "myapp/demo",
  "description": "A demo project",
  "type": "project",
  "autoload": {
    "psr-4": {
      "App\\": "src/"
    }
  },
  "require": {
    "monolog/monolog": "^3.0"
  }
}

Generate the autoloader:

composer dump-autoload

Now create a class at src/Models/User.php:

<?php
namespace App\Models;

class User
{
  public function __construct(
    private string $name,
    private string $email
  ) {}

  public function getName(): string
  {
    return $this->name;
  }

  public function getEmail(): string
  {
    return $this->email;
  }
}

Use the class without requiring the file:

<?php
require __DIR__ . '/vendor/autoload.php';

use App\Models\User;

$user = new User('Alice', 'alice@example.com');
echo $user->getName() . ' - ' . $user->getEmail();

Output:

Alice - alice@example.com

Creating and Publishing a Package

Create a reusable package. Structure:

my-package/
  composer.json
  src/
    Greeting.php

composer.json:

{
  "name": "myapp/greeting",
  "description": "A simple greeting library",
  "type": "library",
  "autoload": {
    "psr-4": {
      "MyApp\\Greeting\\": "src/"
    }
  },
  "require": {
    "php": ">=8.1"
  }
}

src/Greeting.php:

<?php
namespace MyApp\Greeting;

class Greeting
{
  public function say(string $name): string
  {
    return "Hello, $name! Welcome to Composer packages.";
  }
}

Publish to Packagist by pushing the code to a public GitHub Repository and submitting the repository URL at https://packagist.org/packages/submit. Once approved, anyone can install it:

composer require myapp/greeting

Using Composer Scripts

Define scripts to automate common tasks:

{
  "scripts": {
    "test": "vendor/bin/phpunit",
    "lint": "phpcs --standard=PSR12 src/",
    "check": ["@lint", "@test"]
  }
}

Run them with:

composer test
composer lint
composer check

Common Mistakes

  1. Committing vendor directory: The vendor directory should be in .gitignore. Other developers run composer install to recreate it from composer.lock.
  2. Forgetting to commit composer.lock: Without the lock file, different developers may get different versions, causing "it works on my machine" bugs.
  3. Using dev-master without minimum-stability: Composer ignores dev branches unless you set "minimum-stability": "dev" in composer.json or use "dev-master" as the version constraint.
  4. Not running composer dump-autoload after adding classes: PSR-4 autoloading needs a fresh autoloader file after new classes are created. Run composer dump-autoload.
  5. Over-constraining versions: Using exact versions like "1.2.3" prevents security patches. Prefer ^1.2 for flexibility within major versions.

Practice Questions

  1. What is the difference between composer install and composer update?

    • composer install reads composer.lock and installs exact versions. composer update recalculates dependencies and overwrites composer.lock.
  2. How do you add a package only for development?

    • Use composer require --dev phpunit/phpunit to add it to the require-dev section.
  3. What is the purpose of the autoload section in composer.json?

    • It tells Composer how to load classes automatically using PSR-4, PSR-0, classmap, or files autoloading strategies.
  4. How do you remove a package?

    • Run composer remove vendor/package. Composer removes the files and updates composer.json.
  5. Challenge: Create a custom Composer package that provides a Markdown-to-HTML converter. Publish it to a private Satis repository and require it from another project.

Mini Project

Build a command-line CSV processing tool that uses Composer dependencies:

  • Require league/csv for CSV reading and writing.
  • Require symfony/console for CLI command handling.
  • Require monolog/monolog for logging.
  • Create a CsvProcessor class in the App\ namespace that merges two CSV files by a common column.
  • Configure PSR-4 autoloading for the App\ namespace.
  • Write a console command that accepts input file paths and an output file path.

FAQ

What is Composer?

Composer is the dependency manager for PHP. It installs, updates, and autoloads libraries, ensuring every developer uses the same versions.

How do I update a single package?

Run composer update vendor/package to update only that package and its dependencies while respecting version constraints.

What is Packagist?

Packagist is the default package repository for Composer. It hosts over 300,000 PHP packages that can be required with composer require.

What is the vendor directory?

The vendor directory contains all installed packages and the Composer autoloader. It is generated by composer install or composer update and should not be committed.

How do I use a private Composer repository?

Configure a Satis or Toran Proxy server, or use VCS repositories in composer.json to point to private Git repositories.

What's Next

Now that you can manage dependencies, learn the coding standards that make PHP packages interoperable with PSR Standards.

Built by the developers of DodaTech

Doda Browser, DodaZIP & Durga Antivirus Pro