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.
Architecture fit. The package addresses a narrow, real hygiene problem: .env drift from .env.example across developers and environments, resulting in orphaned keys, undocumented variables, and onboarding friction. Architecturally it is a thin, dev-tooling-only wrapper — a service provider registering one or more Artisan commands that parse .env, diff against .env.example, and rewrite the file in example order. It has no runtime footprint, no middleware, no config publishing, and no bearing on application request paths. That makes it trivially removable, but it also means it sits outside the product surface: this is a developer-experience utility, not a platform capability.
Integration feasibility. Mechanically easy — a require-dev install and an Artisan invocation. The real feasibility question is trust, not effort. Any tool whose primary function is rewriting a secrets file in place deserves disproportionate scrutiny relative to its size. .env is a deceptively hard format: quoted and unquoted values, inline # comments, # inside quoted values, escaped quotes, multiline values, ${VAR} interpolation, export prefixes, and trailing comments all break naive line-based parsers. If the parser round-trips loosely, the command silently mangles a credential and the failure surfaces later as an auth error with no obvious cause.
Technical risk. High, concentrated in three places:
illuminate/support and PHP constraints will likely block installation on a current stack without a fork. Zero dependents also means zero downstream bug discovery — we would be the only ones exercising it..env without a documented atomic write or backup is a local-outage vector. Presence or absence of a dry-run/check mode is the single most important thing to verify.Key questions.
${} interpolation byte-for-byte outside the reordering?.env but absent from .env.example handled — dropped, appended, or reported? Silent deletion of a live variable would be disqualifying.include/environment-specific .env.* files, or only .env?Stack fit. Laravel-only, dev-only. It belongs in require-dev and never in a deploy pipeline, container image, or production filesystem. If any part of the adoption path involves running it against a production .env, the answer is no.
Migration path. Do not depend on the upstream package. The MIT license and small surface make vendoring the right move: read the source, fork it into an internal Artisan command under our own namespace, and harden the parser (or delegate parsing to vlucas/phpdotenv's adapter, which Laravel already ships transitively, rather than maintaining a bespoke tokenizer). This converts an unmaintained third-party dependency into ~200 lines of owned, reviewable code with no supply-chain or upgrade exposure. Cost is measured in hours, not sprints.
Compatibility. Assume the upstream constraint set targets Laravel 8 / PHP 8.0. On a modern stack, expect a fork regardless of intent — so plan the fork as step one rather than as a contingency. If we instead pin upstream, we inherit a dependency that blocks the next Laravel major.
Sequencing.
.env files (quoted secrets, inline comments, ${} refs, multiline certs).--write as an explicit opt-in with an automatic .env.backup timestamped copy..env.example and committed config expectations. Nothing that writes to a developer's .env runs automatically.Maintenance. Upstream maintenance is effectively zero — treat the package as feature-frozen source material. Post-fork, the carrying cost is genuinely small: the logic is a parser plus a reorder, and the surface is one command. The real ongoing obligation is keeping the .env fixture corpus current as new variable types appear (base64 blobs, JSON values, PEM blocks).
Support. No upstream support channel worth relying on; one star and zero dependents mean no community backstop. Internally, ownership should sit with platform/DevEx, not with whichever team first asked for it. Documented failure recovery is mandatory: "restore from .env.backup" must be in the runbook before the first write-mode invocation.
Scaling. Not a scaling concern in the conventional sense — it is O(variables) on a file with tens of lines, and it never runs in the request path. The scaling dimension that matters is fleet-wide consistency: the value only materializes if the check runs in CI across all services, which requires .env.example to be treated as a real contract. That is a process change, not a tooling one, and it is where most of the actual effort lives.
Failure modes.
| Failure | Impact | Mitigation |
|---|---|---|
| Parser mangles a quoted/multiline secret | Silent corruption; app misbehaves with cryptic auth/connection errors | Fixture-tested parser or phpdotenv delegation; mandatory backup before write |
Variable present in .env but absent from example gets dropped |
Local or shared-environment outage | Default to report-only; require explicit flag to delete anything |
| Package blocked by Laravel/PHP constraint after upgrade | Broken install for every developer | Fork eliminates this entirely |
Run against production .env |
Credential loss and config drift at the worst possible moment | Dev-only install; environment guard in the command itself |
| Maintainer disappears / repo deleted | Low — MIT license permits continued use of the snapshot | Vendor into our repo; do not rely on Packagist availability |
Ramp-up. Near-zero for users — one Artisan command and a one-line README addition. Near-zero for the implementing engineer as well, which is precisely why the fork-and-harden path is affordable and the third-party dependency is not worth defending.
Recommendation. Do not adopt as a dependency. Extract it as a pattern: fork, harden the parser, default to dry-run, ship the CI drift check first, and gate any in-place rewrite behind an explicit flag and a backup. The underlying problem — .env.example as an enforced contract — is worth solving; this specific artifact, at one star and four years stale, is worth reading rather than installing.
How can I help you explore Laravel packages today?