EasyТеория6 min

Основы Composer

Установка, конфигурация, команды, семантическое версионирование, автозагрузка PSR-4

Что такое Composer и зачем он нужен

Composer — это менеджер зависимостей для PHP. Он позволяет объявлять библиотеки, от которых зависит ваш проект, и управлять их установкой и обновлением. Composer работает на уровне проекта (не глобально, как системные пакетные менеджеры), устанавливая пакеты в директорию vendor/ внутри проекта.

Ключевые задачи Composer:

  • Управление зависимостями — автоматическая установка и обновление библиотек
  • Автозагрузка классов — единый автозагрузчик для всего проекта (PSR-4, PSR-0, classmap, files)
  • Скрипты — автоматизация рутинных задач (проверка кода, очистка кэша)
  • Управление версиями — семантическое версионирование и фиксация зависимостей

До Composer PHP-разработчики вручную скачивали библиотеки, копировали файлы, подключали через require/include. Это приводило к конфликтам версий, дублированию кода и невоспроизводимым сборкам.

Установка Composer

Глобальная установка (рекомендуется для локальной разработки)

# Download installer
php -r "copy('https://getcomposer.org/installer', 'composer-setup.php');"

# Verify installer hash (always check getcomposer.org/download for current hash)
php -r "if (hash_file('sha384', 'composer-setup.php') === 'EXPECTED_HASH') { echo 'Installer verified'; } else { echo 'Installer corrupt'; unlink('composer-setup.php'); } echo PHP_EOL;"

# Install globally
php composer-setup.php --install-dir=/usr/local/bin --filename=composer

# Cleanup
php -r "unlink('composer-setup.php');"

# Verify installation
composer --version

Установка через Docker (рекомендуется для проектов)

# In your Dockerfile
FROM php:8.4-fpm

# Install Composer from official image
COPY --from=composer:latest /usr/bin/composer /usr/bin/composer

# Set working directory
WORKDIR /app

# Copy dependency files first (layer caching)
COPY composer.json composer.lock ./

# Install dependencies
RUN composer install --no-dev --optimize-autoloader --no-scripts
# docker-compose.yml
services:
  php:
    build: .
    volumes:
      - .:/app

# Usage:
# docker compose exec php composer require monolog/monolog
# docker compose exec php composer install

Локальная установка (per-project)

# Install Composer locally in the project
php -r "copy('https://getcomposer.org/installer', 'composer-setup.php');"
php composer-setup.php
php -r "unlink('composer-setup.php');"

# Use with php prefix
php composer.phar install

Структура composer.json

Файл composer.json — это сердце Composer. Он описывает проект и его зависимости.

Полный пример composer.json

{
    "name": "mycompany/my-project",
    "description": "Description of the project",
    "type": "project",
    "license": "MIT",
    "authors": [
        {
            "name": "John Doe",
            "email": "[email protected]"
        }
    ],
    "minimum-stability": "stable",
    "prefer-stable": true,
    "require": {
        "php": ">=8.4",
        "symfony/framework-bundle": "^7.2",
        "doctrine/orm": "^3.3",
        "monolog/monolog": "^3.8"
    },
    "require-dev": {
        "phpunit/phpunit": "^11.5",
        "phpstan/phpstan": "^2.1",
        "friendsofphp/php-cs-fixer": "^3.68"
    },
    "autoload": {
        "psr-4": {
            "App\\": "src/"
        }
    },
    "autoload-dev": {
        "psr-4": {
            "App\\Tests\\": "tests/"
        }
    },
    "scripts": {
        "test": "phpunit",
        "analyse": "phpstan analyse",
        "cs-fix": "php-cs-fixer fix",
        "check": [
            "@analyse",
            "@test"
        ],
        "post-install-cmd": [
            "@auto-scripts"
        ],
        "post-update-cmd": [
            "@auto-scripts"
        ]
    },
    "config": {
        "optimize-autoloader": true,
        "sort-packages": true,
        "allow-plugins": {
            "symfony/flex": true
        }
    }
}

Разбор ключевых полей

name — уникальное имя пакета в формате vendor/package. Обязательно для публикуемых пакетов.

type — тип пакета:

  • library (по умолчанию) — обычная библиотека
  • project — приложение
  • metapackage — пустой пакет, объединяющий зависимости
  • composer-plugin — плагин для Composer

minimum-stability — минимально допустимая стабильность пакетов: dev, alpha, beta, RC, stable (по умолчанию).

prefer-stable — при установке Composer предпочтёт стабильную версию, даже если minimum-stability разрешает нестабильные.

require — зависимости для production. Устанавливаются всегда.

require-dev — зависимости для разработки (тесты, линтеры, отладка). Не устанавливаются с флагом --no-dev.

composer.lock — зачем нужен

Файл composer.lock фиксирует точные версии всех установленных пакетов (включая транзитивные зависимости). Это гарантирует воспроизводимость сборки.

Когда коммитить composer.lock

Тип проекта Коммитить lock? Почему
Приложение (project) Да, всегда Все разработчики и CI получают одинаковые версии
Библиотека (library) Нет Потребители библиотеки должны самостоятельно разрешать зависимости
# .gitignore for a library
/vendor/
composer.lock

# .gitignore for a project
/vendor/
# composer.lock — NOT in gitignore!

Как работает lock-файл

# First install: resolves versions, creates lock file
composer install
# Creates: composer.lock with exact versions

# Subsequent installs: reads lock file, installs exact versions
composer install
# Reads: composer.lock, ignores version constraints from composer.json

# Update: re-resolves versions, updates lock file
composer update
# Updates: composer.lock with new resolved versions

Основные команды Composer

Инициализация проекта

# Interactive project initialization
composer init

# Will ask:
# - Package name (vendor/name)
# - Description
# - Author
# - Minimum Stability
# - Package Type
# - License
# - Dependencies (require)
# - Dev dependencies (require-dev)

Управление зависимостями

# Add a production dependency
composer require monolog/monolog

# Add a specific version
composer require monolog/monolog:^3.0

# Add a development dependency
composer require --dev phpunit/phpunit

# Remove a dependency
composer remove monolog/monolog

# Install all dependencies from lock file
composer install

# Install without dev dependencies (production)
composer install --no-dev

# Update all dependencies
composer update

# Update specific package
composer update monolog/monolog

# Update with all transitive dependencies
composer update --with-all-dependencies

Информационные команды

# Show installed packages
composer show

# Show details of a specific package
composer show monolog/monolog

# Show installed packages as a tree
composer show --tree

# Show outdated packages
composer outdated

# Show direct outdated dependencies only
composer outdated --direct

# Why is a package installed?
composer why monolog/monolog

# Why can't a package be installed?
composer why-not monolog/monolog 4.0

# Validate composer.json
composer validate

# Validate with strict mode
composer validate --strict

Автозагрузка

# Regenerate autoloader
composer dump-autoload

# Optimized autoloader (generates classmap)
composer dump-autoload --optimize

# Classmap-authoritative (only loads from classmap)
composer dump-autoload --classmap-authoritative

Семантическое версионирование (SemVer)

Composer использует семантическое версионирование (SemVer) для определения совместимости пакетов.

Формат версии: MAJOR.MINOR.PATCH

  • MAJOR (1.x.x → 2.x.x) — несовместимые изменения API
  • MINOR (1.1.x → 1.2.x) — новый функционал, обратная совместимость сохранена
  • PATCH (1.1.1 → 1.1.2) — исправления багов, обратная совместимость сохранена

Операторы версий в Composer

{
    "require": {
        "vendor/package-a": "1.2.3",
        "vendor/package-b": ">=1.2",
        "vendor/package-c": ">=1.2 <2.0",
        "vendor/package-d": "~1.2.3",
        "vendor/package-e": "^1.2.3",
        "vendor/package-f": "1.2.*",
        "vendor/package-g": "^0.3.0",
        "vendor/package-h": "dev-main"
    }
}

Подробный разбор операторов

Оператор Пример Эквивалент Описание
Точная версия 1.2.3 =1.2.3 Только эта версия
>= >=1.2 >=1.2.0 Эта версия и выше
Диапазон >=1.2 <2.0 — Между версиями
~ (тильда) ~1.2.3 >=1.2.3 <1.3.0 Последняя цифра может расти
^ (каретка) ^1.2.3 >=1.2.3 <2.0.0 Совместимые с SemVer
* (wildcard) 1.2.* >=1.2.0 <1.3.0 Любой patch
^0.x ^0.3.0 >=0.3.0 <0.4.0 Для pre-1.0 пакетов

Самый важный оператор — ^ (каретка). Он разрешает все обратно совместимые обновления. Это рекомендуемый оператор для большинства случаев.

{
    "require": {
        "^1.2.3": "allows 1.2.3, 1.2.4, 1.3.0, 1.9.99 — but NOT 2.0.0",
        "~1.2.3": "allows 1.2.3, 1.2.4, 1.2.99 — but NOT 1.3.0",
        "^0.3.0": "allows 0.3.0, 0.3.1, 0.3.99 — but NOT 0.4.0 (pre-1.0 special)"
    }
}

composer install vs composer update — КРИТИЧЕСКАЯ РАЗНИЦА

Это одна из самых частых ошибок новичков. Разница принципиальна:

composer install

composer install
  1. Читает composer.lock
  2. Устанавливает точные версии из lock-файла
  3. Если composer.lock отсутствует — работает как composer update (создаёт lock)

Когда использовать: В CI/CD, на production, при клонировании проекта, при первой настройке окружения.

composer update

composer update
  1. Читает composer.json
  2. Разрешает зависимости заново
  3. Устанавливает новейшие подходящие версии
  4. Обновляет composer.lock

Когда использовать: Когда хотите обновить зависимости. Только на машине разработчика, с последующим тестированием.

Наглядная разница

# SCENARIO: composer.json has "monolog/monolog": "^3.0"
# composer.lock has monolog/monolog 3.5.0
# Latest available: monolog/monolog 3.8.1

# composer install → installs 3.5.0 (from lock)
# composer update → installs 3.8.1 (resolves from json, updates lock)

# CRITICAL CI/CD MISTAKE:
# ❌ WRONG: using "composer update" in CI/CD pipeline
# ✅ RIGHT: using "composer install --no-dev --optimize-autoloader"

Типичный рабочий процесс

# Developer wants to add a package:
composer require guzzlehttp/guzzle

# Developer wants to update packages:
composer update
# Review changes, run tests
# Commit updated composer.lock

# CI/CD pipeline:
composer install --no-dev --optimize-autoloader --no-interaction

# Another developer joins the team:
git clone project
composer install
# Gets exact same versions as everyone else

Автозагрузка PSR-4

PSR-4 — стандарт автозагрузки, который связывает пространства имён (namespaces) с директориями файловой системы.

Настройка PSR-4 в composer.json

{
    "autoload": {
        "psr-4": {
            "App\\": "src/",
            "App\\Infrastructure\\": "infrastructure/"
        }
    },
    "autoload-dev": {
        "psr-4": {
            "App\\Tests\\": "tests/"
        }
    }
}

Правила маппинга

Namespace prefix маппится на директорию. Класс App\Service\UserService ищется в файле src/Service/UserService.php.

Namespace: App\Entity\User
Mapping:   App\ → src/
File:      src/Entity/User.php

Namespace: App\Tests\Service\UserServiceTest
Mapping:   App\Tests\ → tests/
File:      tests/Service/UserServiceTest.php

Структура проекта

project/
├── composer.json
├── composer.lock
├── vendor/
│   └── autoload.php          # Generated autoloader
├── src/
│   ├── Entity/
│   │   └── User.php          # App\Entity\User
│   ├── Service/
│   │   └── UserService.php   # App\Service\UserService
│   └── Controller/
│       └── HomeController.php # App\Controller\HomeController
└── tests/
    └── Service/
        └── UserServiceTest.php # App\Tests\Service\UserServiceTest

Использование автозагрузчика

<?php

declare(strict_types=1);

// Include Composer's autoloader — single entry point for all classes
require_once __DIR__ . '/vendor/autoload.php';

use App\Service\UserService;
use App\Entity\User;

// Classes are automatically loaded, no manual require needed
$service = new UserService();
$user = new User(name: 'John', email: '[email protected]');

autoload-dev для тестов

Секция autoload-dev загружается только при composer install (не с --no-dev). Это позволяет разделить production и test автозагрузку.

{
    "autoload": {
        "psr-4": {
            "App\\": "src/"
        },
        "files": [
            "src/helpers.php"
        ]
    },
    "autoload-dev": {
        "psr-4": {
            "App\\Tests\\": "tests/",
            "App\\DataFixtures\\": "fixtures/"
        }
    }
}

После изменения autoload необходимо перегенерировать автозагрузчик:

composer dump-autoload

Скрипты в composer.json

Скрипты позволяют автоматизировать задачи при определённых событиях Composer или запускать их вручную.

Встроенные события

{
    "scripts": {
        "pre-install-cmd": "echo 'About to install dependencies'",
        "post-install-cmd": [
            "@php bin/console cache:clear",
            "@php bin/console assets:install"
        ],
        "post-update-cmd": [
            "@php bin/console cache:clear"
        ],
        "pre-autoload-dump": "echo 'About to regenerate autoloader'",
        "post-autoload-dump": [
            "App\\ScriptHandler::postAutoloadDump"
        ]
    }
}

Пользовательские скрипты

{
    "scripts": {
        "test": "phpunit --colors=always",
        "test:coverage": "phpunit --coverage-html coverage/",
        "analyse": "phpstan analyse --memory-limit=512M",
        "cs-fix": "php-cs-fixer fix",
        "cs-check": "php-cs-fixer fix --dry-run --diff",
        "check": [
            "@cs-check",
            "@analyse",
            "@test"
        ],
        "build": [
            "@composer install --no-dev --optimize-autoloader",
            "@php bin/console cache:warmup"
        ]
    }
}
# Run custom scripts
composer test
composer analyse
composer check
composer build

Packagist и приватные репозитории

Packagist.org

Packagist — основной публичный репозиторий для PHP-пакетов. По умолчанию Composer ищет пакеты именно здесь.

# Search for packages
composer search monolog

# Show package info from Packagist
composer show monolog/monolog --all

Приватные пакеты

Для проприетарного кода используются приватные репозитории.

VCS Repository (Git):

{
    "repositories": [
        {
            "type": "vcs",
            "url": "[email protected]:mycompany/private-package.git"
        }
    ],
    "require": {
        "mycompany/private-package": "^1.0"
    }
}

Satis (self-hosted Packagist):

{
    "repositories": [
        {
            "type": "composer",
            "url": "https://satis.mycompany.com"
        }
    ]
}

Private Packagist (SaaS):

{
    "repositories": [
        {
            "type": "composer",
            "url": "https://repo.packagist.com/mycompany/"
        }
    ]
}

Практические примеры

Создание нового Symfony-проекта

# Create new Symfony project
composer create-project symfony/skeleton my-project

cd my-project

# Add commonly used packages
composer require symfony/orm-pack
composer require symfony/maker-bundle --dev
composer require symfony/debug-bundle --dev

# Add testing tools
composer require --dev phpunit/phpunit
composer require --dev phpstan/phpstan
composer require --dev phpstan/phpstan-symfony

# Validate configuration
composer validate --strict

# Show dependency tree
composer show --tree

Создание нового Laravel-проекта

# Create new Laravel project
composer create-project laravel/laravel my-laravel-app

cd my-laravel-app

# Add packages
composer require laravel/sanctum
composer require spatie/laravel-permission

# Add dev tools
composer require --dev larastan/larastan
composer require --dev laravel/pint

# Check for outdated packages
composer outdated --direct

Типичный рабочий процесс в команде

# Developer A adds a new package
composer require league/flysystem
# Commit both composer.json and composer.lock

# Developer B pulls changes
git pull
composer install
# Gets exact same version of league/flysystem

# Weekly dependency update
composer outdated --direct
composer update --with-all-dependencies
# Run full test suite
composer test
# If tests pass, commit updated lock file

Проверь себя

5 из 12

Какую команду нужно выполнить после изменения секции autoload в composer.json?

Какой раздел composer.json используется для автозагрузки тестовых классов?

Что означает minimum-stability: 'dev' с prefer-stable: true?

Как запустить пользовательский скрипт 'check', определённый в composer.json?

Какая команда используется в CI/CD пайплайне для production?