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

Config Writer Laravel Package

devdojo/config-writer

A Laravel package for writing and updating config values in PHP config files at runtime, letting you persist settings changes without editing files by hand.

View on GitHub
Deep Wiki
Context7

Getting Started

Install

composer require devdojo/config-writer

There is no documented service provider contract worth relying on. Before writing a line of application code, open the package's composer.json and src/ — the whole thing is small enough to read in one sitting (it is a DevDojo/Wave internal utility extracted into a package, not a maintained ecosystem library). Confirm:

  1. Whether a service provider + facade is auto-discovered (extra.laravel.providers / aliases).
  2. The exact public method signatures. Anything you read in blog posts or older Wave code may not match the current src/.
  3. Whether it depends on vlucas/phpdotenv directly or hand-rolls string replacement.

Where to look first

  • src/ — typically two concerns: a config file writer (reads config/foo.php with include, mutates the array, re-exports with var_export) and an env writer (line-based key/value replacement in .env).
  • tests/ — if present, they are the only reliable spec for edge-case behaviour (quoting, ordering, comments).
  • Any config/ file shipped by the package for path overrides.

First use case

The canonical shape of this package is an installer/settings screen: an admin submits SMTP or API credentials, and you persist them so the next request picks them up without a redeploy.

use DevDojo\ConfigWriter\ConfigWriter; // verify namespace against src/

$writer = new ConfigWriter();

// Persist into config/mail.php
$writer->writeConfig('mail', 'from.address', $request->input('from_address'));

// Persist into .env (illustrative signature)
$writer->writeEnv('MAIL_FROM_ADDRESS', $request->input('from_address'));

Artisan::call('config:clear');

If the package only exposes one of these two capabilities, use it for that one and reach for laravel/framework's own helpers or a hand-rolled class for the other — do not bend the API.

Implementation Patterns

1. Installer / first-run wizard The primary pattern. Treat the writer as the persistence layer of a setup flow: validate input with a FormRequest, write config and env in a transaction-ish sequence, then clear caches. Keep the write behind an artisan command or controller action that returns a clear success/failure response, because the failure modes (permissions) are user-fixable.

2. Wrap it in your own class Do not scatter new ConfigWriter() through the codebase. Bind an interface in a service provider and implement it with this package. Given the package's adoption profile (1 star, 0 dependents, last release May 2024), you want a one-file swap path when it goes stale or when Wave's assumptions don't match yours.

// app/Contracts/SettingsWriter.php
interface SettingsWriter {
    public function put(string $key, mixed $value): void;
}

Register your ConfigWriterSettingsWriter in AppServiceProvider and inject the contract everywhere else.

3. Write-through with an in-memory update A config-file write does not affect the running request if the config is already loaded (or cached). Pair every write with an in-memory set so the current request sees the new value:

$writer->writeConfig('services.stripe', 'key', $value);
config(['services.stripe.key' => $value]);   // current process
Artisan::call('config:clear');               // future processes

4. Idempotent bootstrapping Guard writes so re-running an installer is safe:

if (empty(config('mail.from.address'))) {
    $writer->writeConfig('mail', 'from.address', $default);
}

5. Artisan commands as the call site Prefer php artisan app:set-mail-config over a web route that writes files. It sidesteps most permission/deploy issues, is trivially scriptable in CI, and makes the operation auditable. The web form can Artisan::call() it if needed.

6. Testing against a temp path Copy the relevant config/*.php and .env into a Storage::fake-style temp directory, point the writer at it (if it accepts a path), assert on the resulting file contents, then restore. Snapshot the file after a write and diff — this package's output formatting (indentation, trailing newlines, array syntax) is the thing most likely to break your git diffs.

7. Deployment scaffolding Useful for generating a .env for a new environment from a template: read a stub, write environment-specific values, hand it off to your provisioning step. This is a better fit than runtime writes if your production filesystem is read-only (Vapor, containers with immutable images).

Gotchas and Tips

Config cache silently wins. If config:cache has run, your beautifully written config/foo.php is never read. Any write must be followed by config:clear (and ideally queue:restart for long-running workers). Forgetting this is the number one "the package doesn't work" bug report.

Filesystem permissions. PHP needs write access to config/ and .env. On Forge/Ploi the forge user owns these; under a web-server-context CLI (or with www-data running PHP-FPM) writes fail. Under Docker/Kubernetes with a read-only root filesystem, this package cannot function at all — prefer env vars injected by the platform.

.env parsing is where hand-rolled writers break. Watch for:

  • Values containing # (treated as a comment by naive parsers).
  • Values with spaces or = (must be quoted).
  • Existing quoted values — double-quoting produces "\"foo\"".
  • Multiline values and empty-value handling (KEY= vs KEY="").
  • Duplicate keys: some writers replace the first, silently leaving a second definition that dotenv may prefer.

Test each of these explicitly against your own .env before shipping. If the package's implementation does a plain preg_replace on the line, assume it does not handle them all.

No atomicity, no locking. Expect a file_put_contents-style write. Two concurrent requests writing different keys can lose one update, and a crash mid-write can truncate the file. For anything beyond single-admin installers, wrap writes in a queue job with WithoutOverlapping, or use a database-backed settings table and materialise config from it at boot.

Env changes don't apply to the current process. Changing .env does not update $_ENV/getenv()/env() in the running request. This is expected PHP behaviour but surprises people who write .env and then call env('NEW_KEY') in the same request.

Version pin it. Last release May 2024, one star, zero dependents — assume no maintainer response and no security patches. Pin an exact version ("devdojo/config-writer": "1.0.0") and put a composer outdated check in CI so a silent break is noticed. Budget for vendoring the two classes into app/Support/ if the package rots; the code is small enough that this is genuinely the lower-risk option for anything long-lived.

Extension points are thin. Realistically your options are: subclass the writer and override the file-writing method, bind your own implementation behind an interface, or copy the source. There is no plugin system, no events, and no config file to tune behaviour. Plan accordingly and keep the surface area of your integration to one class.

Debugging checklist when a write "doesn't take":

  1. cat the file — did it actually change?
  2. php artisan config:clear / check bootstrap/cache/config.php exists.
  3. Check file ownership and mode (ls -l .env config/).
  4. Check for a second definition of the key further down .env.
  5. Check for OPcache/realpath implications if the file is included by another process.

Don't let writes touch version control. .env should already be gitignored; make sure any generated config/ files that contain secrets are covered too, or write secrets exclusively to .env and read them via env() in your config files.

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.
frankyso/ipaymu
3mdikram/worldmoneywords
snowsoft/config
itmosoft/laravel-subscriptions
larva/laravel-ai-qwen
diephp/sequences
users-au/socialite-provider
twidpay/twid-logger
mrnewport/laravel-plaid
mrnewport/laravel-repo
mrnewport/laravel-docsign
mrnewport/laravel-stow
mrnewport/laravel-flow
mrnewport/laravel-priceable
mrnewport/laravel-nestedterms
fredmeng/laravel-apidoc-generator
itstructure/laravel-multilingual-tools
pdustdar/elasticsearch
markupai/php-sdk
rlacerda83/lumem-microservice-shipment