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?
2. When should you use composer install vs update?
3. What is a content hash in composer.lock?
Flashcards
Question
What is composer.lock?
Click to reveal answer
Answer
Lock file with exact package versions for reproducible builds
Question
install vs update?
Click to reveal answer
Answer
install reads lock file, update resolves new versions
Question
What is content hash?
Click to reveal answer
Answer
Hash of composer.json to detect lock file staleness
Question
When to regenerate lock file?
Click to reveal answer
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