Skip to content
intermediate Phase 93 · Composer

composer.lock

composer.lock - lock file purpose, reproducible builds, updating lock files

30m
0 problems
Topic Progress 0%

Lock File Purpose

What is composer.lock?

  composer.json (flexible constraints)
       │
       â–¼
  composer update
       │
       â–¼
  composer.lock (exact versions)

Lock File Structure

{
    "_readme": ["This file locks the dependencies of your project..."],
    "content-hash": "abc123...",
    "packages": [
        {
            "name": "magento/framework",
            "version": "103.0.5",
            "version_normalized": "103.0.5.0",
            "source": {
                "type": "git",
                "url": "https://github.com/magento/magento2.git",
                "reference": "abc123"
            },
            "dist": {
                "type": "zip",
                "url": "https://api.github.com/repos/magento/magento2/zipball/abc123",
                "reference": "abc123"
            },
            "require": {
                "php": "^8.1"
            },
            "autoload": {
                "psr-4": {
                    "Magento\\Framework\\": "lib/internal/Magento/Framework/"
                }
            }
        }
    ],
    "packages-dev": [],
    "aliases": [],
    "minimum-stability": "stable",
    "stability-flags": [],
    "prefer-stable": true,
    "platform": [],
    "platform-dev": [],
    "plugin-api-version": "2.3.0"
}

Why Lock Files Matter

// Without lock file - different versions each install
// Dev: composer install → gets v2.4.6
// Prod: composer install → gets v2.4.7 (breaking!)

// With lock file - exact same versions
// Dev: composer install → v2.4.6
// Prod: composer install → v2.4.6 (consistent!)

Reproducible Builds

Install vs Update

# Install (uses lock file)
composer install
# Reads composer.lock, installs exact versions
# Does NOT modify lock file

# Update (modifies lock file)
composer update
# Reads composer.json, resolves new versions
# Updates composer.lock

# Update specific package
composer update vendor/package
# Updates only that package in lock file

Lock File Validation

namespace Vendor\Composer\Lock\Validation;

class LockFileValidator
{
    public function validate(
        string $jsonPath,
        string $lockPath
    ): ValidationResult {
        $json = json_decode(file_get_contents($jsonPath), true);
        $lock = json_decode(file_get_contents($lockPath), true);

        // Check content hash
        $expectedHash = $this->calculateContentHash($json);
        if ($lock['content-hash'] !== $expectedHash) {
            return new ValidationResult(false, 'Lock file outdated');
        }

        // Check required packages exist
        foreach ($json['require'] as $package => $constraint) {
            if (!$this->packageExists($lock, $package)) {
                return new ValidationResult(false, "Missing package: $package");
            }
        }

        return new ValidationResult(true);
    }
}

CI/CD Lock File Strategy

# CI Pipeline
steps:
  - name: Validate lock file
    run: composer validate --strict

  - name: Check lock file freshness
    run: |
      composer install --no-scripts --prefer-dist
      composer check-platform-reqs

  - name: Build with lock file
    run: |
      composer install --no-dev --optimize-autoloader

Lock File Management

Common Operations

# Regenerate lock file
rm composer.lock
composer update

# Update all dependencies
composer update

# Update specific package
composer update vendor/package

# Update with dependency resolution
composer update --with-dependencies vendor/package

# Dry run (preview changes)
composer update --dry-run

# Lock without installing
composer lock

Lock File Conflicts

namespace Vendor\Composer\Lock\Conflict;

class LockFileConflictResolver
{
    public function resolve(
        array $installed,
        array $required
    ): ConflictResult {
        $conflicts = [];

        foreach ($required as $package => $constraint) {
            $installedVersion = $installed[$package] ?? null;

            if ($installedVersion && !$this->satisfies($installedVersion, $constraint)) {
                $conflicts[] = [
                    'package' => $package,
                    'installed' => $installedVersion,
                    'required' => $constraint,
                ];
            }
        }

        return new ConflictResult(
            empty($conflicts),
            $conflicts
        );
    }
}

Platform Requirements

{
    "config": {
        "platform": {
            "php": "8.2.0",
            "ext-redis": "6.0.0",
            "ext-intl": "*"
        }
    }
}

Troubleshooting

Common Issues

# Error: Your requirements could not be resolved
composer update --no-dev

# Error: Lock file outdated
composer update --lock

# Error: Package not found
composer clear-cache
composer update

# Error: Version conflict
composer why-not vendor/package 2.0

# Debug dependency tree
composer why vendor/package
composer depends vendor/package

Lock File Debugging

namespace Vendor\Composer\Lock\Debug;

class LockFileDebugger
{
    public function analyze(string $lockPath): AnalysisResult
    {
        $lock = json_decode(file_get_contents($lockPath), true);

        $analysis = [
            'total_packages' => count($lock['packages']),
            'dev_packages' => count($lock['packages-dev']),
            'platform_requirements' => $lock['platform'] ?? [],
            'minimum_stability' => $lock['minimum-stability'],
            'prefer_stable' => $lock['prefer-stable'],
        ];

        // Find outdated packages
        $analysis['outdated'] = $this->findOutdated($lock['packages']);

        return new AnalysisResult($analysis);
    }
}

Lock File Best Practices

namespace Vendor\Composer\Lock\BestPractice;

class LockFileBestPractice
{
    public function getRecommendations(): array
    {
        return [
            'Commit lock file to version control',
            'Use composer install in production (not update)',
            'Regenerate lock file when adding dependencies',
            'Validate lock file in CI pipeline',
            'Use --prefer-dist for faster installs',
            'Use platform config for consistent PHP versions',
        ];
    }
}

Quiz

1. What does composer.lock ensure?

Question 1 options

2. When should you use composer install vs update?

Question 2 options

3. What is a content hash in composer.lock?

Question 3 options

Flashcards

Question

What is composer.lock?

Answer

Lock file with exact package versions for reproducible builds

Question

install vs update?

Answer

install reads lock file, update resolves new versions

Question

What is content hash?

Answer

Hash of composer.json to detect lock file staleness

Question

When to regenerate lock file?

Answer

When adding/changing dependencies in composer.json

Revision Notes

Key Takeaways

  • 1. composer.lock ensures reproducible builds across environments
  • 2. composer install reads lock file, composer update modifies it
  • 3. Content hash detects when lock file is outdated
  • 4. Commit lock file to version control
  • 5. Use platform config for consistent PHP versions

Interview Tips

  • Explain the difference between install and update
  • Discuss lock file role in CI/CD pipelines
  • Describe content hash validation
  • Talk about handling dependency conflicts

Cheat Sheet

composer.lock:
  Exact versions → reproducible builds
  Content hash → staleness detection

Commands:
  composer install → read lock file
  composer update → modify lock file
  composer lock → generate without install

Best Practices:
  Commit lock file
  install in production
  update in development
  validate in CI