- Knowledge
- technology
- OOP
- Tips
- Programming
- Tips
- Tutorial
- SEO
- Ranking
- Knowledge
- Special Day
- Seo
- Bug
- Data science
- Seo
- artificial intelligence
- Machine Learning
- Robotics
- happyNewYear2021
- newYearEve
- 2021
- Automation
- Smart Home
- Career
- Best Practices
- Git
- Logging
- Web Fundamentals
- DNS
- HTTPS
- Performance
- AI Tools
- ChatGPT
- Claude
- Gemini
- Laravel
- Eloquent
- MySQL
- HTTPS
- TLS
- Web Security
- Certificates
- Developer Life
- Debugging
- Docker
- DevOps
- Transactions
- Queues
- LLMs
- AI
- AI Coding
- Developer Tools
- React Native
- Expo
- Kate PMS
- Mobile Apps
- Laravel
- Authentication
- Sanctum
- Cookies
- API Design
- Payments
- Idempotency
- DeepSeek
- Open Source AI
- LLMs
- AI News
- Git
- Version Control
- AI Coding
- Prompting
- PHP
- Checklist
- MCP
- AI Agents
- OpenAI
- Architecture
- Microservices
- Modular Monolith
- Estimation
- Developer Life
- Project Planning
- Humour
- OAuth
- OpenID Connect
- Authentication
- Embeddings
- Vector Search
- RAG
- pgvector
- OpenAI
- GPT-4.1
- Codex CLI
- Events
- Testing
- Clean Code
- Maintainability
- Code Review
- Webhooks
- API
- Security
- Claude Code
- Workflow
- AI
- LLM
- Prompt Injection
- Mobile
- React
- Networking
- TCP
- UDP
- HTTP/3
- CLAUDE.md
- AWS
- Cloud Security
- Backups
- PHPUnit
- Software Engineering
- Leadership
- Communication
- RAG
- Embeddings
- AI Engineering
- IT Infrastructure
- Networking
- Access Control
- CI/CD
- GitHub Actions
- Gemini CLI
- Claude Code
- JavaScript
- Async/Await
- Node.js
- Promises
- Security
- Cryptography
- Passwords
- MySQL
- Database
- Vibe Coding
- Software Quality
- DNS
- Code Reading
- Onboarding
- Productivity
- Background Jobs
- Developer Humour
- Estimates
- Dev Life
- JWT
- o3-mini
- DeepSeek R1
- Rate Limiting
- Kate PMS
- E-Signing
- Audit Trail
- REST
- GraphQL
- API Design
- Laravel 12
- Upgrade Guide
- Open Source
- Self-Hosting
- Task Scheduling
- Cron
- Secrets
- CORS
- PHP
- PHP-FPM
- OPcache
- GitHub Copilot
- Software Architecture
- Engineering
- TypeScript
- JavaScript
- Type Safety
- AI Security
- React Native
- Product Design
- AI Agents
- Kiro
- Queues
- Redis
- RabbitMQ
- AWS SQS
- Nginx
- Apache
- GPT-5
- gpt-oss
- Clean Code
- Architecture
- Naming
- Documentation
- Career
- ADR
- Teamwork
- Supply Chain
- Kate HRM
- HR Software
- Permissions
- System Design
- Pagination
- SSH
- Linux
- Big O
- Databases
- Laravel Boost
- MCP
- Developer Skills
- Validation
- Databases
- Indexes
- Code Quality
- Deployment
- Developer Humour
- Feature Flags
- Code Review
- Pull Requests
- Docker
- Cursor
- Authorization
- RBAC
- Gemini
- Long Context
- PHP 8.4
- Caching
- Dependency Injection
- Web Performance
- Browser
- CSS
- Database
- Migrations
- ChatGPT
- AI for Developers
- Monitoring
- On-Call
- REST
- Backend
- SQL
- NoSQL
- Database Design
- Coding Agents
- Claude 4
- API Resources
- REST API
- Load Balancing
- Scaling
- AWS
- AI Tools
- Claude
- Sora 2
- CTE
- 2FA
- TOTP
- Programming Languages
- Prompts
- Developer Workflow
- API Gateway
- APIs
- Passport
- API Auth
- Learning
- Burnout
- Developer Growth
- Web Development
- SEO
- Kate Mall
- ChatGPT Atlas
- Agent Skills
- Middleware
- Laravel 12
- Collections
- Context Window
- Monitoring
- Commit Messages
- Self Review
- Growth
- Regex
- Programming Basics
- Text Processing
- Database Design
- Normalization
- Linux
- Server Security
- Linux Foundation
- Open Standards
- Legacy Code
- Documentation
- AI Workflow
- File Uploads
- Test Data
- Hashing
- Performance
- Caching
- Enums
- Scope Creep
- Estimation
- Codex
- Gemini CLI
- Timezones
- Carbon
- Bugs
- PHP 8.5
- Gemini 3
- GPT-5.1
- Data Integrity
- Event Loop
- Async
- Opus 4.5
- AI Models
- React
- Forms
- Frontend
- Backups
- AI Images
- DALL-E
- Midjourney
- Race Conditions
- Concurrency
- Legacy Code
- Refactoring
- Senior Engineer
- Scope
- LLM
- CDN
- Web
- Sub-Agents
- Soft Deletes
- Audit Log
- Concurrency
- AI Learning
- NestJS
- AI Evals
- Policies
- SPF DKIM DMARC
- Unicode
- UTF-8
- Knowledge Graph
- Value Objects
- Technical Debt
- Feature Flags
- Laravel Pennant
- Deployment
- Copilot
- Composer
- Dependencies
- Artisan
- Automation
- AWS S3
- Object Storage
- Cloud
- Small Language Models
- Ollama
- Production
- Sessions
- HTTP
- Mentoring
- SQL
- Virtual Machines
- Web Development
- HTTP/2
- QUIC
- Web Performance
- AI Integration
- LLM API
- SOLID
- OOP
- Hosting
- Serverless
- Merge Conflicts
- Temperature
- AI Development
- Reverse Proxy
- Nginx
- Infrastructure
- Verification
- Passkeys
- WebAuthn
- Teams
- Communication
- Stakeholders
- Monorepo
- CI/CD
- Versioning
- JSON Schema
- Livewire
- Inertia
- Meetings
- Distributed Systems
- Privacy
- Full-Stack
- T-Shaped Skills
- Money
- Notifications
- Web Security
- HTTP Headers
- CSP
- Function Calling
- Load Testing
- k6
- Data Extraction
- Debugging
- WebSockets
- SSE
- Real-Time
- Laravel Reverb
- Infrastructure as Code
- Terraform
- Side Projects
- Laravel Pint
- OpenAPI
- Swagger
- UX
- Multimodal
- Jest
- Pair Programming
- APIs
- Rate Limiting
- Resilience
- Dev Humour
- Design Tokens
- JWT
- API Keys
- Sessions
- PHPStan
- Rector
- Incidents
- Reporting
- Dashboards
- Zero Trust
- IAM
- Search
- Laravel Scout
- Junior Developers
- Mentoring
- Images
- WebP
- AVIF
- Bug Reports
- Let's Encrypt
- Design Docs
- Software Design
- Observers
- Replication
- Accountability
- Data Structures
- Reliability
- LLM Memory
- Error Handling
- Payments
- Payment Gateway
- Webhooks
- PCI DSS
- Observability
- OpenTelemetry
- Personal Brand
- Writing
- Conventions
- Dates
- Scheduling
- Disaster Recovery
- Compression
- Brotli
- Deadlines
- Developer Habits
- State Machines
- Tech Roles
- UUID
- ULID
- Horizon
- Planning
- Engineering Culture
- Ownership
- Soft Skills
- Socialite
- Cost Control
- Collations
- Unicode
- Octane
- PostgreSQL
What Actually Happens When You Run composer install
About Post
You clone a project, type composer install, watch a wall of green text scroll past, and get on with your day. It's probably the PHP command you run most and read least.
Then one day it fails with an error about a PHP version you're not even using, or prints a warning about the lock file being out of date, or works on your laptop and installs something slightly different on the server. And suddenly it matters what that command actually does.
So let's slow it down and follow it, step by step, from the moment you press Enter.
Two files, two jobs
Everything starts with the difference between these two files, and most Composer confusion comes from mixing them up.
composer.json | composer.lock | |
|---|---|---|
| Says | What versions you're willing to accept | The exact versions you actually got |
| Example | "laravel/framework": "^12.0" | laravel/framework at one exact release, with its source reference |
| Written by | You | Composer |
| Covers | Your direct dependencies | Every package, including dependencies of dependencies |
Think of composer.json as a shopping list ("milk, any brand, not expired") and composer.lock as the receipt ("this exact carton, from this shelf, at this time"). If you want someone else to end up with exactly what you have, you give them the receipt.
Step 1: is there a lock file?
This is the fork in the road.
- If
composer.lockexists, Composer installs exactly what it lists. No thinking, no choosing. The same versions on every machine. - If it doesn't, Composer has to work out a set of versions that satisfies every constraint in your project and in every package's own
composer.json. That's dependency resolution, and it's effectively whatcomposer updatedoes. Then it writes a new lock file.
If the lock file exists but doesn't match composer.json (someone edited the JSON and didn't update), Composer warns you that the lock file is not up to date. Don't ignore that one. It means the lock no longer describes the project.
Step 2: checking your platform
Packages declare what they need from your environment: a PHP version, and extensions like ext-mbstring or ext-intl. Composer checks these against the PHP running the command.
This is where the confusing errors come from. If your terminal's PHP differs from the one serving your app (very common on machines with several PHP versions, including XAMPP setups), Composer checks the wrong one. Run php -v in the same terminal before blaming the package.
You'll find advice online to use --ignore-platform-reqs. It makes the error go away by installing packages your PHP may not be able to run. Treat it as a last resort, not a fix.
Step 3: downloading, with a cache
For each package in the lock file, Composer downloads the release (usually a zip archive) and extracts it into vendor/. Downloads are cached in Composer's home directory, which is why the second install of the same versions is so much faster than the first.
Note that Packagist, the main package repository, only hosts metadata: which versions exist and where to get them. The code itself usually comes from wherever the package lives, such as GitHub.
Step 4: building the autoloader
This is the step that makes new SomeClass() work without a single require. Composer generates vendor/autoload.php from the autoload rules of every package and of your own project:
"autoload": {
"psr-4": {
"App\\": "app/",
"Database\\Factories\\": "database/factories/"
}
}
PSR-4 is a simple rule: namespace App\Services\PdfService maps to app/Services/PdfService.php. The case has to match exactly on Linux, which is why a class that loads on Windows can fail on the server.
When you add a new namespace mapping, run composer dump-autoload to regenerate the autoloader. In production, --optimize-autoloader builds a full class map so PHP doesn't have to check the file system for every class.
Step 5: running scripts
Finally, Composer runs any scripts defined in composer.json. Laravel uses this: after the autoloader is dumped, it runs php artisan package:discover to register service providers from your packages.
That has a surprising consequence. If composer install fails at this point, the problem often isn't Composer at all. It's your application failing to boot, because Artisan is running your app. A broken config file or a missing environment value can look like a Composer error.
Semantic versioning in two minutes
Versions follow MAJOR.MINOR.PATCH: breaking changes bump the major, new features the minor, fixes the patch. Constraints in composer.json use that convention:
^12.0means at least 12.0, below 13.0. Any non-breaking update. This is the sensible default.~1.2means at least 1.2, below 2.0.~1.2.3is tighter: at least 1.2.3, below 1.3.0.^0.3means at least 0.3.0, below 0.4.0, because before 1.0 every minor version is allowed to break things.*means anything. Please don't.
Semver is a promise, not a guarantee. Package authors do occasionally break things in a minor release, which is exactly why the lock file exists.
The rule: commit composer.lock for every application, and deploy with composer install, never composer update. Updating is a decision you make on purpose, on your machine, in a pull request, with the tests running.
Why committing the lock file matters
- Reproducible installs. Your laptop, CI and production get identical code.
- Reviewable updates. A dependency update shows up as a lock file diff in the pull request, so you can see exactly which packages moved.
- Security audits.
composer auditchecks the exact versions in your lock file against known vulnerabilities.
For libraries the story is different: when someone installs your package, your lock file is ignored. Their project's constraints decide.
And when two branches both changed the lock file and Git reports a conflict, don't hand-edit it. Resolve composer.json, take one branch's lock file, then re-run the composer require or composer update vendor/package commands from the other branch so Composer rebuilds it properly.
The production one-liner
composer install --no-dev --optimize-autoloader --no-interaction
No dev packages, an optimized class map, and no prompts waiting for a human who isn't there. Put it in your deploy script and never think about it again.
What's the strangest composer install failure you've had to debug? Mine usually turn out to be the wrong PHP binary in the terminal.

Be first to comment it...