Back

Values written once

🧭

Is this package for you?

17 reasons, each a before and an after. Select the problems you have and see how many match.

Take the scorecard
♻️

Not every value varies by environment

Your currency is EUR everywhere. Your timeout is 30 everywhere. Writing them into four factories means four places to change and four chances to miss one — and the day you miss one, two environments quietly disagree.

4

environments

2

constant properties

8

repeated literals

Every factory restates everything
development(): new static(
    provider: 'ollama',
    currency: 'EUR', temperature: 0.2,
);
staging(): new static(
    provider: 'openai',
    currency: 'EUR', temperature: 0.2,
);
production(): new static(
    provider: 'openai',
    currency: 'EUR', temperature: 0.2,
);

Change the currency and you edit three lines. Miss one and it drifts.

Constant once, variable per environment
__construct(
    public string $provider,              // varies
    public string $currency = 'EUR',      // once
    public float $temperature = 0.2,      // once
) {}

development(): new static(provider: 'ollama');
production():  new static(provider: 'openai');

// the one that differs just passes it:
staging(): new static(provider: 'openai', temperature: 0.9);

One place to change. The exception is still allowed, and it is obvious.

💡

There is no feature here. That is the feature.

This is a plain PHP constructor default — nothing the package invents. A shared() array merged in by the package would mean building instances reflectively instead of with new static(...), which costs the constructor's own type checking, named-argument autocomplete, and the ability to read a settings class as ordinary PHP.

So it works with show, --all, diff, check, masking, local overrides and toArray() — not because each was taught about it, but because there is nothing new to teach them.

Generating one

--shared takes name=value pairs and writes them as defaults instead of repeating them in every factory. Output below is real.

Run

php artisan env-settings:make ProbeSharedSettings \
  --properties="provider:string,currency:string,timeout:int" \
  --shared="currency=EUR,timeout=30"

Get

public function __construct(
    public string $provider,
    // Same in every environment — an environment
    // that differs passes its own.
    public string $currency = 'EUR',
    public int $timeout = 30,
) {}

public static function development(): static
{
    return new static(
        provider: '', // TODO: set development value
    );
}

Note which properties got a // TODO: only provider. The shared values are already set, so env-settings:check has nothing to complain about — it only chases the values that were genuinely left blank.

Which properties belong in the signature

✓ Same everywhere today

Currency, a default page size, a retry backoff your team standardised on. Give it a default and let the rare exception pass its own value — which then reads as a deliberate difference rather than one of four near-identical literals.

✕ Same today, by coincidence

Two environments happening to share a hostname this week is not a constant. If the value is meant to differ, keep it in the factories where --all and diff will keep showing it to you.

Read the docs Local overrides All four commands Is this for you? Back to the demo