# Composer and Dependency Management in PHP

- آدرس: https://di9.ir/blog/en/composer-php-dependency-management-guide
- نویسنده: danidiba
- انتشار: 2026-09-23T11:21:00+03:30
- به‌روزرسانی: 2026-09-23T11:21:00+03:30
- دسته: PHP
- برچسب‌ها: autoload، Composer، PHP، لاراول، وابستگی

> Composer is the standard package manager for PHP. Learn what composer.json and composer.lock do, how to install and update packages, how autoloading works and what to watch for on shared hosting.

We used to download a library file, drop it in a folder and call it with `require`. The result was forgotten old versions that nobody could locate. Composer brings order to this: you say which packages you need and which versions are acceptable, and it does the rest.

Laravel is built entirely on Composer, and even in WordPress most professional tools are installed with it. So learning it is one of the first investments for a PHP developer.

## What Composer actually does

Composer is PHP's package manager. It has three main jobs:

1. It downloads the packages you need, and their dependencies, from the public Packagist registry.
2. It finds compatible versions and records them exactly.
3. It builds an autoloader so classes load without a manual `require`.

Install it by following the official guide at getcomposer.org, because the method differs by operating system. After installing, `composer --version` should respond.

## Starting a project and installing a package

Run this in the project folder:

```bash
composer init
composer require monolog/monolog
```

The first command creates the `composer.json` file and the second installs the package. Three things now appear: `composer.json`, `composer.lock` and the `vendor` folder. Simple usage:

```php
<?php
declare(strict_types=1);

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

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

$log = new Logger('app');
$log->pushHandler(new StreamHandler(__DIR__ . '/app.log'));
$log->warning('User signed in');
```

A single `require` for the autoloader is enough; all other classes are found automatically.

## composer.json and composer.lock

You write `composer.json`, and it says what you want:

```json
{
    "name": "acme/shop",
    "require": {
        "php": "^8.1",
        "monolog/monolog": "^3.0"
    },
    "require-dev": {
        "phpunit/phpunit": "^10.0"
    },
    "autoload": {
        "psr-4": {
            "App\\": "src/"
        }
    }
}
```

The `^3.0` constraint means any version compatible with 3 that has no breaking changes. Composer itself writes `composer.lock`, recording the exact version of every package. The golden rule is:

| File | Who writes it | In Git? |
| --- | --- | --- |
| composer.json | You | Yes |
| composer.lock | Composer | Yes (for applications) |
| vendor/ | Composer | Usually no |

The lock file guarantees that your server and your machine run exactly the same versions. To manage these files in Git, see [Git for beginners](https://di9.ir/blog/%D8%A2%D9%85%D9%88%D8%B2%D8%B4-%DA%AF%DB%8C%D8%AA-%D8%A8%D8%B1%D8%A7%DB%8C-%D8%B4%D8%B1%D9%88%D8%B9).

## Autoloading with PSR-4

The `autoload` section in the example above says that classes in the `App` namespace live in the `src` folder. So the class `App\Service\Mailer` must be in `src/Service/Mailer.php`:

```php
<?php
declare(strict_types=1);

namespace App\Service;

final class Mailer
{
    public function send(string $to, string $subject): bool
    {
        // sending logic
        return true;
    }
}
```

After changing the autoload section, run `composer dump-autoload` to rebuild the map. The file name must match the class name, with the same upper and lower case, because Linux servers are case-sensitive.

## Everyday commands

- `composer install`: installs the versions recorded in the lock file. Use it on servers and for teammates.
- `composer update`: updates packages within the constraints and changes the lock file. Use it on your development machine.
- `composer require vendor/pkg`: adds a new package.
- `composer remove vendor/pkg`: removes a package.
- `composer outdated`: lists packages that have newer versions.
- `composer audit`: checks your dependencies against a list of known security vulnerabilities.

Run `composer audit` every so often; an outdated package is one of the most common ways in for an attacker. We cover the other ways in [PHP code security](https://di9.ir/blog/%D8%A7%D9%85%D9%86%DB%8C%D8%AA-%DA%A9%D8%AF-php).

## Deploying on shared hosting

On a production server, don't install development packages, and optimize the autoloader:

```bash
composer install --no-dev --optimize-autoloader
```

If your host has no terminal access, run the same command on your own machine and upload the `vendor` folder. Keep your local PHP version close to the host's version. Other shared hosting tips are in the [shared hosting checklist for Laravel](https://di9.ir/blog/%DA%86%DA%A9-%D9%84%DB%8C%D8%B3%D8%AA-%D9%87%D8%A7%D8%B3%D8%AA-%D8%A7%D8%B4%D8%AA%D8%B1%D8%A7%DA%A9%DB%8C-%D8%A8%D8%B1%D8%A7%DB%8C-%D9%84%D8%A7%D8%B1%D8%A7%D9%88%D9%84).

> Never leave the `vendor` folder directly accessible from the web. It is better placed outside the site's public root.

## Safety notes

Don't install unknown packages: check the repository name, the number of users and the date of the last update. Installing a package means running code you didn't write. If you run Composer as root, those same scripts run with full privileges. Also, don't put passwords or API keys in `composer.json`.

## When something breaks

You will see three problems more than any others. First, the "Class not found" message, which almost always means the namespace doesn't match the file path, or `composer dump-autoload` wasn't run after changing autoload. Second, version conflicts: two packages want incompatible versions of one dependency. The command `composer why-not vendor/pkg 2.0` explains what is blocking the install. Third, PHP version incompatibility; the `config.platform.php` section in `composer.json` tells Composer to resolve versions for the host's PHP, not your machine's PHP.

```json
{
    "config": {
        "platform": { "php": "8.1.0" },
        "sort-packages": true
    }
}
```

## How to spot a good package

Before `composer require`, spend two minutes. Check whether the repository is still maintained, how many open issues are going unanswered, how many other packages depend on it and whether its license fits your project. A package that brings a hundred dependencies for a ten-line job is usually not worth it. Every new dependency is code you must keep updated and a risk you must accept.

## Summary

- Composer manages packages, versions and autoloading.
- `composer.json` is what you want and `composer.lock` is the exact installed version; keep both in Git.
- Run `composer install` on the server and run `update` only on your development machine.
- PSR-4 autoloading means the file name, folder and namespace must all agree.
- In production, use `--no-dev --optimize-autoloader`.
- Run `composer audit` regularly and install only trusted packages.

## پرسش‌های متداول

### What is the difference between composer install and composer update?

install sets up exactly the versions recorded in composer.lock, which suits servers and teams. update upgrades packages within the constraints in composer.json and rewrites the lock file, so run it on your development machine.

### Should I commit the vendor folder to Git?

Usually not. Add vendor to .gitignore and keep composer.json and composer.lock so anyone can rebuild the same dependencies with one command. If your host has no terminal access, you can build vendor on your own machine and upload it with your files.

### What should I do if my shared hosting doesn't have Composer?

Install the dependencies on your own computer with `composer install --no-dev --optimize-autoloader` and upload the vendor folder. Keep your local PHP version close to the host's version to avoid incompatibilities.

### Is running Composer as root dangerous?

Package scripts run with your privileges during installation, so don't run Composer as root and only install trusted packages. Composer also warns you when it runs as root.
