hpwebdeveloper/laravel-env-settings
A small Laravel package for managing environment settings, letting you read and update .env values from your application instead of editing files by hand. Useful for admin-configurable options and simpler deployments.
Architecture fit. The package addresses a real and common Laravel weakness: .env is an untyped key-value store with no review surface, no autocomplete, and no compile-time guarantees. Moving non-secret, environment-varying values into committed PHP classes under app/Settings converts configuration drift into a diffable, reviewable artifact. The design is idiomatic Laravel — container singletons, app()->environment() resolution rather than env(), config:cache-safe, constructor injection, backed enums for closed value sets. There is no runtime service, no network call, no external dependency. The scope is deliberately narrow and the boundaries are documented: secrets stay in .env, everything else is a settings class. That clarity is the package's strongest architectural property.
Integration feasibility. High. Integration is additive — publish one config file, list classes in register, scaffold with env-settings:make. Nothing is removed from the existing config system; existing config() calls continue to work, so adoption can be incremental per module. The --path/--namespace options support non-standard layouts, and the #[Environment] attribute covers APP_ENV values outside the default map (qa, uat, demo) — essential for organisations with more than the three canonical environments.
Technical risk. The dominant risk is maturity, not capability. Seventeen stars and a single maintainer imply low community validation, no evidence of a broad contributor base, and no independent security review. The API depends on PHP 8.1+ features (enums, promoted constructors, attributes) and the package asserts @phpstan-consistent-constructor discipline, so static analysis configuration is part of the adoption cost, not an optional extra. The most consequential risk is governance rather than code: the package's entire premise is that engineers correctly classify "secret" versus "non-secret." A misjudged #[Sensitive] property or a credential pasted into a factory method lands in git history permanently. Masking heuristics on property names containing key, secret, password, or token are a helpful backstop but are explicitly a guess.
Key questions.
APP_ENV switching — is the singleton safe to reuse across requests?EnvironmentSettings is a small base class; forking or vendoring is plausible, but that must be verified against the actual surface area.)Stack fit. Best suited to a Laravel monolith or a small number of first-party services where the same set of non-secret values must differ across three or more environments — API endpoints, model names, queue names, timeouts, feature modes. It fits poorly where configuration is already centralised in a config service, or where services are polyglot and a Laravel-only config mechanism would fragment the story.
Migration path. Incremental and low-risk, in four stages:
config/env-settings.php, scaffold one class for a low-blast-radius domain (e.g. outbound HTTP timeouts), register it, and read it via envSettings(...) in one or two call sites. Measure the review-experience delta.env-settings:make generates TODO placeholders; fill them immediately and in the same PR, never across a follow-up.php artisan env-settings:check --env=production to CI on the deploying branch. This is the highest-value single step: it is a static check, needs no network or production credentials, and converts "forgot to fill in staging" into a build failure rather than a 2 a.m. incident.ENV_SETTINGS_OVERRIDE and gitignore app/Settings/Overrides/ for developers who need per-machine values.Sequencing matters: run the pilot before mandating anything, and land the CI gate before the backfill wave, so unfinished classes cannot accumulate.
Compatibility. No conflict with config:cache. Avoid app_path() inside the config file — the docs are explicit that caching would freeze the build machine's absolute path; use null or a relative override_path. Existing config() reads are untouched, so rollback is "stop using the helper" rather than "revert the release."
Maintenance. Low mechanical burden, non-trivial governance burden. The package adds no runtime process to monitor and no external service to page on. The recurring cost is human: settings classes are code and will drift, so they need the same review rigour as any other committed code. Budget for an owner of the standards document and for periodic env-settings:show --all reviews — that matrix is the fastest way to answer "how do these four environments actually differ?" and to spot properties repeated identically in every factory that should have become constructor defaults.
Support. Single-maintainer, low-adoption dependency. Treat it as a "vendor and be prepared to fork" component rather than a "consume and forget" one. Pin the version, read the changelog on upgrade, and keep the surface area of usage narrow — the helper function and constructor injection are the whole API, so a fork would be contained. No commercial support exists; internal ownership must be named.
Scaling. Resolution is one singleton per registered class per request, which is negligible. The real scaling axis is class count and organisational breadth: past roughly a dozen classes, adopt the documented composition pattern (a root settings object whose factories call child factories) so callers read envSettings(AppSettings::class)->auth->domain rather than juggling a dozen imports. Namespace-per-module via --path keeps ownership aligned with team boundaries.
Failure modes. Ranked by consequence:
#[Sensitive], which masks output but does not protect the repository.env-settings:check in CI; the check only reports empty values when another environment supplies a real one, so deliberate empties need #[AllowEmpty].APP_ENV mismatch — an unmapped value falls through to fallback_environment (development), so a demo box can quietly run dev settings. Mitigate with #[Environment] attributes on the class so the mapping is visible at the definition site.override_path and an onboarding check.Ramp-up. One concept to learn — "secrets in .env, everything else in a typed class" — plus three artisan commands. A mid-level Laravel engineer is productive in under a day. The residual cost is cultural, not technical: env() is deeply habitual, and the package fails quietly when the convention is ignored rather than loudly when it is broken. Pair the rollout with a lint rule or review checklist, and make env-settings:show --all the default answer to environment-difference questions so the tooling earns its place.
How can I help you explore Laravel packages today?