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

Dotenv Editor Laravel Package

koel/dotenv-editor

A Laravel package for programmatically reading, updating, and deleting variables in .env files, with backup support and a simple API for managing environment configuration at runtime.

View on GitHub
Deep Wiki
Context7

Getting Started

koel/dotenv-editor is a maintained fork of brotzka/laravel-dotenv-editor that gives you a programmatic API over the raw .env file (read keys, set/delete values, create/restore backups). It is intentionally thin: no database, no encryption, no queueing — just file manipulation with a dotenv-aware parser.

Install and confirm wiring

composer require koel/dotenv-editor

On Laravel 5.5+ the service provider and DotenvEditor facade alias are auto-discovered. If you are on an older version, register Koel\DotenvEditor\DotenvEditorServiceProvider in config/app.php and add the facade alias manually. Note that most tutorials online are for the original Brotzka\DotenvEditor namespace; the API is nearly identical, but verify imports against vendor/koel/dotenv-editor/src/ rather than copy-pasting old snippets.

Publish the config so you can point the package at the right file and backup directory:

php artisan vendor:publish --provider="Koel\DotenvEditor\DotenvEditorServiceProvider"

Review config/dotenv-editor.php (filePath, backup path/settings), then verify the web server user can write .env and the backup directory.

First use case — an admin settings screen

The canonical day-to-day use is letting an administrator update SMTP/mail credentials or a third-party API key from the UI instead of SSH-ing into the server:

use DotenvEditor;

DotenvEditor::load();                     // read the current file into memory
DotenvEditor::setKeys([
    ['key' => 'MAIL_HOST', 'value' => 'smtp.postmarkapp.com'],
    ['key' => 'MAIL_USERNAME', 'value' => $username],
    // ...
]);
DotenvEditor::save();                     // writes the whole file back

Where to look first

  1. vendor/koel/dotenv-editor/src/DotenvEditor.php — the entire public API is one class; skim it before trusting the README.
  2. config/dotenv-editor.php — file path and backup behavior.
  3. The package's tests, if present, show parsing quirks (quotes, comments, empty values).

Start by writing a single key to a throwaway copy of .env (point filePath at a fixture) before wiring it into a controller.

Implementation Patterns

Wrap it in your own service, not controllers. The package is a low-level file editor. Put it behind a class such as App\Services\EnvFileService with methods like updateMailSettings(array $data) so key names, validation, backups, and post-save cache handling live in one place.

Whitelist keys explicitly. Never pass a user-supplied key name straight into setKey(). Accept a form request, map allowed fields to a fixed array of env keys, validate each value (length, allowed characters, email/host format), then call setKeys() once.

Batch, then save once. setKeys([...]) followed by a single save() minimizes write window and diff noise. Avoid save() inside loops.

Read before write. Use keyExists() / getValue() (or parse getKeys()/getContent()) to populate form defaults and to detect no-op updates. This also lets you show "unchanged" and avoid rewriting the file unnecessarily.

Backups as your undo button. The package ships backup helpers (createBackup(), getBackups(), restoreBackup(), deleteBackup()). A safe workflow for bulk edits:

DotenvEditor::load();
$backup = DotenvEditor::createBackup();
try {
    DotenvEditor::setKeys($changes);
    DotenvEditor::save();
} catch (\Throwable $e) {
    DotenvEditor::restoreBackup($backup);
    throw $e;
}

Apply changes to the running app after saving. Writing the file does not update the current process. After a successful save, either:

  • run Artisan::call('config:clear') and reload relevant config values manually,
  • call putenv('KEY=value') for values you need immediately,
  • and for production, Artisan::call('queue:restart') (and octane:reload if applicable).

Common pattern: update .env, clear config cache, then redirect with a message telling the admin the change is applied after workers restart.

Serialize writes with a lock. Treat .env like a shared resource:

Cache::lock('dotenv-editor', 10)->block(5, function () use ($changes) {
    DotenvEditor::load();
    DotenvEditor::setKeys($changes);
    DotenvEditor::save();
});

Audit and mask. Log which keys changed (not their values), by whom, and when. When rendering forms, show a masked placeholder for secrets and only overwrite the key if the admin typed a new value — otherwise getValue() hands you a secret you should never echo back into HTML.

Script it from Artisan when needed. A small command (env:set KEY value --backup) is handy for deploy pipelines or support runbooks, using the same service class as the UI.

Test against a fixture. In tests, override the config filePath to a temp copy before resolving the facade, and assert on file contents. Never let tests touch the real .env.

Group keys with comments. Use addComment() / addEmpty() plus setKeys() to keep the file readable (e.g., a # Mail section); call save() afterward. This is the main reason to prefer the package over hand-rolled file_put_contents — it preserves existing lines and comments reasonably well.

Gotchas and Tips

  • The current process will not see your change. Laravel loads .env once at bootstrap; env() reads already-populated values. After save() you must clear config cache and/or restart workers/Octane. With config:cache active, Laravel ignores .env entirely — document that admins must run php artisan config:clear after editing, or do it programmatically.
  • No automatic quoting/escaping. Values containing spaces, #, =, $, quotes, or newlines can corrupt or silently truncate the line. Wrap values in double quotes yourself, escape " and \$ (phpdotenv interpolates $VAR inside double quotes), and reject multi-line values. Private keys and certificates do not belong in .env via this tool.
  • Empty vs. null is meaningful. KEY= yields an empty string; KEY=null yields null. Choose deliberately and be consistent with how your config reads the value.
  • load() is not implicit forever. The facade is a singleton; if something else modified .env during the request, call load() again before reading. Likewise, getContent()/getKeys() reflect the last load, not disk.
  • No key validation. A typo (MAIL_HOTS) is happily written as a new variable. Whitelist keys in your own code and compare against .env.example in CI to catch drift.
  • Whole-file rewrite, no atomicity guarantees. Two concurrent saves can clobber each other. Use the cache lock above; consider writing to a temp file and renaming if you need stronger guarantees.
  • Permissions bite in containers. The PHP-FPM user needs write access to .env and the backup directory. Bind mounts in Docker often produce root-owned files; check ownership and umask, and surface a clear error if is_writable() fails rather than a generic 500.
  • Backups contain secrets. They land under storage/app/... by default. Keep them out of git, out of public disks, and prune them; a "helpful" backup feature is a credential leak if exposed. Also back up before a restoreBackup() — it overwrites the current file.
  • Do not rotate APP_KEY through a UI. Changing it invalidates encrypted columns, sessions, and signed URLs. Treat it as a deploy-time operation with a migration plan, not an editable field.
  • Missing .env. Ensure filePath points at an existing file; bootstrap it from .env.example if absent, and fail loudly otherwise.
  • Windows/CRLF and formatting churn. The package normalizes line endings; expect noisy diffs if the file was CRLF. Commit .env.example, never .env.
  • Namespace confusion. Old articles use Brotzka\DotenvEditor\.... This fork uses its own namespace; mixing imports causes "class not found" errors that look like installation failures. Clear bootstrap/cache after switching.
  • Low-maintenance dependency. With a single star and a single primary consumer (Koel itself), pin the version, review upgrades, and keep your wrapper thin enough that you can replace the package with ~50 lines of vlucas/phpdotenv + file I/O if it goes stale.
  • Debugging checklist: dump getContent() after load(), write to a fixture path first, confirm the backup directory exists and is writable, and check config('dotenv-editor.filePath') actually resolves where you think.
  • Extension points: override filePath and backup settings via config, extend the DotenvEditor class and rebind it in a service provider if you need custom parsing or logging, and swap the facade binding in tests to a fake.
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.
middlewares/firewall
qubiqx/montapacking
nyoncode/laravel-package-console
pnscripts/filament-broadquill-lite
pnscripts/laravel-sentfold-lite
vleap/mx-sdk-laravel-internal
twidpay/utils
htetmyathlaing/scout-elasticsearch-driver
artisan-toolbox/front-awesome
ls/client-assistant
users-au/laravel-client
cgv/localized-resource
noith/settings
kda/laravel-package
kda/filament-dynamic-navigation
bypersoft/signbox
pairus/product-data
fayne/laravel-filament-cms-core
nodisrupt/laravel-agent
sierratecnologia/media-manager