Weave Code
Weaver
Helps Laravel developers discover, compare, and choose open-source packages. See popularity, security, maintainers, and scores at a glance to make better decisions.
Feedback
Share your thoughts, report bugs, or suggest improvements.
Subject
Message

Laravel Env Normalizer Laravel Package

romanzipp/laravel-env-normalizer

A Laravel package that normalizes your .env file, tidying key ordering and formatting so environment configs stay consistent across projects and teams. Useful for keeping diffs clean and avoiding merge conflicts in shared .env files.

View on GitHub
Deep Wiki
Context7

Getting Started

This package solves one narrow problem: your .env.example is the team's contract, your .env drifts from it, and nobody wants to diff them by hand. Treat it as a local developer hygiene tool, not application code.

Install (dev-only):

composer require --dev romanzipp/laravel-env-normalizer

Laravel's package discovery should register the service provider automatically. Confirm the command exists before doing anything else:

php artisan list | grep env
php artisan env:normalize --help

Read the source first. The package is ~1 star, last released 2021-10-14, and effectively unmaintained. Before you trust it with your .env, spend two minutes in vendor/romanzipp/laravel-env-normalizer/src/ — it is a handful of small classes and you will immediately see exactly how it parses lines (it is a line-oriented parser, not a full dotenv AST). That tells you more about edge-case behavior than any README.

First use case — the one that pays for itself:

  1. cp .env .env.backup (do this every time until you trust the tool).
  2. php artisan env:normalize
  3. git diff --no-index .env.backup .env — read the diff, not just the exit code.

You are looking for two things: keys that got moved (fine) and keys that vanished or got mangled (not fine). On a healthy project the diff is pure reordering plus your custom/legacy variables pushed to the end.

The habit that makes this worth keeping: run it after every git pull that touches .env.example. New keys in the example show up as gaps in your local file, and dead keys accumulate at the bottom where you can see them and delete them.

Implementation Patterns

Sync-on-pull workflow. The realistic day-to-day pattern isn't "normalize on a schedule" — it's "normalize when the example changes."

git pull
php artisan env:normalize
# now open .env and scan the tail: anything after the example block is
# either your local override or a variable the app no longer reads

The tail of the file is your unused-variable report. That's the actual deliverable; the ordering is just a side effect.

Audit drift before a release. When you're not sure whether prod's env matches what the code expects, normalize a copy of the deployed env and diff it against .env.example:

scp prod:/var/www/app/.env ./prod.env.audit
php artisan env:normalize --file=prod.env.audit   # verify the option name with --help
diff <(grep -oE '^[A-Z_]+' .env.example | sort) <(grep -oE '^[A-Z_]+' prod.env.audit | sort)

Even if the --file flag doesn't exist in your version, the grep/diff one-liner gives you the missing-keys answer without the package at all — worth keeping in your back pocket.

Composer script for muscle memory.

"scripts": {
    "env:sync": [
        "@php artisan env:normalize"
    ]
}

Keep it out of post-install-cmd/post-update-cmd. You do not want a Composer update silently rewriting a .env that contains credentials.

Normalize the sibling files too. phpunit.xml reads env vars, and many teams keep .env.testing or .env.ci. Normalize them in the same pass so the whole family stays aligned — but do it as separate, explicit invocations you can eyeball, never in a loop that hides failures.

Pair with config:clear. Any .env mutation invalidates cached config. If you normalize in a script that then runs tests or a serve command:

php artisan env:normalize && php artisan config:clear

CI angle — be realistic. .env is gitignored, so there is nothing to enforce in CI. The only enforceable check is that .env.example itself is complete, and this package won't tell you that. If you want CI coverage, write a ~40-line test that asserts every key referenced in config/*.php via env() exists in .env.example. Don't contort this package into that job.

Gotchas and Tips

Variable interpolation ordering is the real hazard. .env supports ${VAR} references, and those only resolve if the referenced variable appears earlier in the file. Reordering to match .env.example can silently break MAIL_FROM_ADDRESS="${APP_URL}"-style chains. After your first normalize, grep for ${ and verify each one still sits below its source.

Backups are not optional in version one. Whatever backup behavior the command has (check --help — it may or may not write one in your version), assume it doesn't. Copy .env yourself. A tool that reorders a credentials file is one parser bug away from a bad afternoon.

Comments and blank lines get roughed up. Line-oriented normalizers typically hoist variables and strip or strand the # Section header comments you use to group settings. If your .env is heavily commented, expect to re-add the sectioning by hand. If that's a dealbreaker, the tool is fighting you.

Multi-line values will break naive parsers. PEM certificates, JSON service-account blobs, anything with embedded newlines. If your .env contains those, do not run this against it — or extract them to a file reference first.

# inside values. Inline comments are ambiguous in dotenv format. A line like PASSWORD=abc#123 may round-trip differently than you expect. Spot-check any value containing #, spaces, or quotes in the diff.

Unmaintained means you own it. Last release October 2021. On PHP 8.1+/Laravel 9/10/11 you may hit a phpdotenv constraint conflict, a deprecated-API warning, or discovery that just doesn't register. Options, in order of preference:

  1. composer require --dev romanzipp/laravel-env-normalizer -W and see what happens on a throwaway checkout.
  2. If it fights you, vendor the logic — copy the handful of classes into app/Console/Commands/ and register them yourself. For a package this small, forking is cheaper than dependency archaeology.
  3. If even that's too much, the replacement is genuinely short: parse both files line-by-line, build an ordered map from .env.example, emit matching lines from .env in example order, append the leftovers under a # NOT IN .env.example banner. That's a 50-line artisan command and you keep the comments.

Windows / CRLF. If anyone on the team is on Windows, check whether line endings survive the rewrite. A file that flips to CRLF will produce an enormous diff for everyone else and can upset other tooling.

Duplicate keys. Hand-maintained .env files accumulate them. Observe what your version does (last-wins, dedupe, both kept) on a scratch file before running it on a real one — the behavior is unlikely to be documented and may surprise you.

The extension point is the fork button. There's essentially no config file, no events, no middleware here — it's one command. Don't architect around it. Use it for the drift audit, keep it as a --dev dependency, and if the maintenance burden ever exceeds the value, replace it with the artisan command described above and delete the dependency.

Weaver

How can I help you explore Laravel packages today?

Conversation history is not saved when not logged in.
Prompt
Add packages to context
No packages found.
novasa/laravel-language-center
opencage/geocode
adolfoholzer/parameters
livenetworks/ln-starter
shitoudev/permissionmanager
johannesclimacus/laravel-tui
hocvt/seotools
vitalybaev/sypexgeo
amphibee/themosis-ignition
gito-me/fast-excel
frankyso/laravel-ipaymu
geolize-studio/laravel-chile
boomerangui/chat
cgv/localized-resource
noith/settings
kda/laravel-package
kda/filament-dynamic-navigation
bypersoft/signbox
pairus/product-data
fayne/laravel-filament-cms-core