A messy composer.json is rarely the biggest problem in a PHP project, but it is often a reliable signal. When dependency metadata is inconsistent, teams spend more time on avoidable code review comments, merge conflicts, and handover questions. For business owners, operations leads, and agencies, that means slower delivery and more friction in otherwise routine maintenance.
If you want a practical default in 2026, use Composer's own validation tools together with the maintained ergebnis/composer-normalize normalizer. That gives you cleaner diffs, fewer arguments about formatting, and a simple CI check that catches drift early.
What a tidy composer.json should actually do
Tidying composer.json is not just about whitespace. A useful cleanup should:
- keep keys and package lists in a predictable order
- make dependency changes easier to review
- verify the file still matches Composer's schema and lock file expectations
- reduce team-specific formatting habits that create noisy pull requests
That matters most when several developers, contractors, or partner agencies touch the same codebase. The goal is not elegance for its own sake. The goal is less operational drag.
The current best default
Composer itself gives you part of the answer. composer validate --strict checks that your composer.json is valid and warns on things that can cause trouble later. Composer also has a built-in sort-packages setting, which keeps packages alphabetized when people use composer require.
But sort-packages is only partial. It helps with future additions, not full-file normalization. For a complete tidy-up, the maintained tool to use is ergebnis/composer-normalize. It adds a composer normalize command, can show diffs, can run safely in CI with --dry-run, and understands lock-file implications.
A practical setup for team projects
For most agency or in-house PHP projects, this is the setup I would standardize:
composer require --dev ergebnis/composer-normalize
composer config allow-plugins.ergebnis/composer-normalize true
composer normalize
composer validate --strictThat sequence does a few useful things. It installs the normalizer as a dev tool, explicitly allows the plugin in Composer's security model, rewrites the file into a consistent format, and then validates the result. If your organization prefers not to allow project-level Composer plugins, the tool is also available outside the plugin flow, but for most teams this is the simplest path.
If you want future dependency additions to stay cleaner, add the built-in sort setting:
{
"config": {
"sort-packages": true
}
}This does not replace normalization. It simply stops everyday composer require changes from making the file noisier again.
How to use it in CI
Once the file is clean, enforce it. That is where this becomes valuable for operations and delivery teams, not just developers.
composer normalize --dry-run
composer validate --strictThe dry run is the important detail. It lets CI fail fast when someone commits an unnormalized composer.json or an out-of-date lock relationship, without rewriting files inside the pipeline. Reviewers get a clear signal, and formatting corrections stay out of release steps.
If your workflow is strict about lock file updates, read the flags before you automate aggressively. The normalizer can check the lock file and can update its hash when needed, which is usually helpful, but teams should be deliberate about when that happens.
What normalization will not fix
A tool can clean structure, but it will not make weak dependency decisions disappear. Use the cleanup pass to look for a few common issues by hand:
- outdated or duplicate package requirements left behind by earlier refactors
- legacy autoload settings when new code should be using PSR-4
- stale scripts, repositories, or platform constraints that no longer reflect production reality
- a manually maintained
versionfield that probably should not be there for VCS-managed packages
In other words, normalization is a hygiene step, not an architecture review. It makes the file easier to trust, but you still need someone to decide whether the package list, constraints, and scripts make sense for the business.
When this is worth standardizing
If you only touch a small PHP site twice a year, manual cleanup may be enough. If you run several client projects, share developers across teams, or inherit codebases from multiple vendors, standardizing composer.json handling pays back quickly. Reviews get shorter, handovers are smoother, and dependency metadata becomes less personal and more operational.
If you want that kind of cleanup turned into a repeatable delivery rule across projects, not just a one-off tidy-up, this is exactly the sort of process work Greg can help structure.
Need help with this kind of work?
Need a repeatable PHP delivery workflow? Get in touch with Greg.