Tidy Up composer.json with Composer Normalize

Illustrated infographic summarizing: Tidy Up composer.json with Composer Normalize

By Greg Nowak. Updated 2 November 2026.

A routine PHP dependency update should leave a reviewer with a clear question: are these package changes appropriate? When composer.json also contains inconsistent indentation and sections that move between edits, that decision becomes harder to follow.

Composer Normalize gives this file a consistent structure. For business owners and operations leads, the value is a maintenance process that is easier to oversee and hand over. For developers and agency teams, it removes a recurring source of review noise. The useful outcome is a pull request where the dependency decision is easy to find.

Where Composer Normalize fits

composer.json describes the packages your project needs, alongside configuration, scripts, and other metadata. Several tools help maintain it, but each answers a different question:

Review question Command or setting Purpose
Are newly added packages ordered consistently? config.sort-packages Keep package lists sorted during Composer require operations.
Does the manifest follow a consistent structure? composer normalize Normalize the file locally.
Has formatting drifted? composer normalize --dry-run Check normalization without changing files.
Is the manifest valid and its lock file current? composer validate --strict Report validation problems, including warnings.
Use these checks together so reviewers can concentrate on the reason for a dependency change.

Composer’s sort-packages setting applies when require adds packages. It does not standardize every section edited by hand. That broader cleanup is the normalizer’s job.

Install it with explicit plugin permission

Start on a branch with a clean working tree. After reviewing the plugin, run these commands from the project root:

composer config allow-plugins.ergebnis/composer-normalize true
composer config sort-packages true
composer require --dev ergebnis/composer-normalize
composer normalize
composer validate --strict

This installs Composer Normalize as a development dependency. Keeping it in the project makes the chosen version part of the team’s shared setup.

The permission comes first because Composer plugins can execute code. Allow this specific package after review; avoid setting allow-plugins to true for every plugin. Recording the choice also prevents an interactive trust prompt from becoming an unattended installation problem.

Inspect both changed files before committing. Installing the tool adds dependencies, so this first pull request will contain more than formatting. Explain that scope in the description and keep unrelated package upgrades or PHP constraint changes separate.

Keep the lock file changes understandable

For an application, commit composer.lock alongside the manifest. As Composer’s basic usage guide explains, the lock file records resolved versions so contributors, CI, and deployment installations can use the same dependency set.

Normalization checks an existing lock file and can update its content hash. A hash change does not itself mean package versions changed. Review the actual diff before describing the result as formatting only.

If the lock file was already stale, investigate the dependency edit that caused it. Avoid running a broad composer update merely to silence the check: that can introduce upgrades outside the intended work. The normalizer’s --no-check-lock and --no-update-lock switches should serve a documented workflow, rather than become routine ways around failures.

For shared libraries, Composer also recommends committing the lock file. It stabilizes the library’s own development environment; projects consuming the library resolve dependencies using their own constraints and lock files. Library compatibility testing therefore needs broader coverage than one locked installation.

Make CI enforce the agreed baseline

Once the initial cleanup is reviewed, add these commands to the pull request pipeline:

composer install --no-interaction
composer normalize --dry-run
composer validate --strict

The documented dry-run behavior is to fail with exit code 1 when normalization is needed or the lock file is out of date, and show a diff without modifying files. Contributors fix the issue locally and commit the correction.

Run this job with development dependencies installed and plugins enabled. A production installation using --no-dev should not be expected to provide the normalizer command. Also configure the pipeline to stop or report failure when any command fails.

Strict validation treats warnings as failures too. Read the existing output before making it mandatory. For a private application that will never be published to Packagist, composer validate --strict --no-check-publish can exclude publication suitability errors while retaining other checks. Document that choice so future maintainers understand it.

Use the review to check what formatting cannot tell you

A clean manifest still needs a human decision. During maintenance or an agency handover, ask whether development tools belong in require-dev, which integration needs each direct dependency, and who owns custom repositories and scripts. Record uncertain items as follow-up work rather than expanding a formatting change indefinitely.

Check the deployment assumptions too. If the project uses config.platform, confirm that it represents the intended target. After installing dependencies in the deployment environment or matching image, run:

composer check-platform-reqs --no-dev

This checks actual PHP and extension requirements, ignoring the platform override. Keep application tests and release checks alongside it; normalization alone cannot establish that a release works.

Give the workflow an owner

Put the local fix command and CI expectations in the project’s contributor notes. For agencies maintaining several PHP sites, include them in repository templates and handover documentation. Agree who handles a failed check and who approves dependency changes.

If those responsibilities keep falling between your business and its development suppliers, Greg can help review your PHP delivery workflow and turn the findings into a practical maintenance and handover process.

Related on GrN.dk

Need help with this kind of work?

Discuss your PHP delivery workflow with Greg Get in touch with Greg.

Sources

Latest articles

Does your ChatGPT subscription cover website translation? Understand API credits, access and a WordPress workflow that turns approved Danish content into translation drafts.

An internal AI can keep quoting a deleted policy. Check document updates, indexed passages and cached answers to find where outdated guidance survives.

Codex drew all ten pages of my Ninjai comic from the script Claude wrote in the first test. What made that handover work, and what it cost.

ChatGPT delivered ten painted comic pages; Claude drew one page in code. A practical look at AI tool selection, creative briefs and approval decisions.

Get missing supporting documents under control with a clearly scoped AI workflow that sorts replies, coordinates reminders and gives the bookkeeper a clear follow-up list.

Know what dmesg and journalctl can tell you after a reboot, how to find previous-boot logs, and how to check that retention covers your investigation window.

Check how your chatbot identifies itself as AI, where requests for human help actually go, and what customers encounter when support is unavailable.

Start with one website change on board.nowa.dk. Write a clear task, answer questions as they arise and review the result before giving an AI agent more work.

Keep AI search visibility, training preferences and assistant access separate. Use a practical policy matrix to check Cloudflare settings and test key public pages.

Let AI draft Black Friday campaigns using approved product data. Check prices and recipients, and secure approval before sending the campaign from Mailchimp.