Back

The four commands

🧭

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
⌨️

Scaffold, inspect, compare, verify

Settings live in PHP classes, so the tooling is a set of artisan commands rather than a dashboard. Every one of them takes its arguments on the command line — or asks you for them if you leave them off.

Cheat sheet

Command Does Exits non-zero
env-settings:make Scaffolds a settings class and registers it on failure only
env-settings:show Prints resolved values for the current environment on failure only
env-settings:diff Compares one class across two environments on failure only
env-settings:check Reports values left at their placeholder yes — when incomplete

env-settings:make

Scaffold a class

Writes the class, its constructor and one factory per environment — then appends it to the register array so it is never left inert. Values start as placeholders with a // TODO beside them.

Run

php artisan env-settings:make WebhookSettings \
  --properties="endpoint:string,signing_secret:string,retries:int" \
  --sensitive="signing_secret"
Settings class created: app/Settings/WebhookSettings.php

  → Registered \App\Settings\WebhookSettings::class in config/env-settings.php

Get

public function __construct(
    public string $endpoint,
    #[Sensitive] public string $signing_secret,
    public int $retries,
) {}

public static function production(): static
{
    return new static(
        endpoint: '', // TODO: set production value
        signing_secret: '', // TODO
        retries: 0, // TODO
    );
}
--properties

name:type pairs — string, int, float, bool, or an enum class name

--sensitive

names to mark #[Sensitive]; each must appear in --properties

--path

target directory (default app/Settings)

--namespace

explicit namespace, else derived from --path or class_namespace

env-settings:show

What resolves right now

Resolves every registered class against the current APP_ENV and prints the values with their types. Pass a class to narrow it to one.

php artisan env-settings:show
php artisan env-settings:show "App\Settings\AiSettings"
[ AiSettings ] — Environment: production
+------------------+--------+------------------------+
| Property         | Type   | Value                  |
+------------------+--------+------------------------+
| provider         | string | openai                 |
| text_model       | string | gpt-4o                 |
| embeddings_model | string | text-embedding-3-large |
| max_tokens       | int    | 8000                   |
| temperature      | float  | 0.2                    |
+------------------+--------+------------------------+
--all Every environment side by side

A settings class states every environment in one file — that is the whole argument for having one. This is the command that shows it. Without it, “where do these differ?” across four environments took six diff runs merged in your head.

php artisan env-settings:show --all
php artisan env-settings:show "App\Settings\AiSettings" --all
[ AiSettings ] — development, production, staging, testing
+--------------------+------------------+------------------------+------------------------+------------------+
| Property           | development      | production             | staging                | testing          |
+--------------------+------------------+------------------------+------------------------+------------------+
| provider *         | ollama           | openai                 | openai                 | ollama           |
| text_model *       | llama3.2         | gpt-4o                 | gpt-4o-mini            | llama3.2         |
| embeddings_model * | nomic-embed-text | text-embedding-3-large | text-embedding-3-small | nomic-embed-text |
| max_tokens *       | 1000             | 8000                   | 2000                   | 1000             |
| temperature *      | 0.9             | 0.2                    | 0.5                    | 0.9              |
+--------------------+------------------+------------------------+------------------------+------------------+
* = differs somewhere

Real output from this demo. Note testing matching development exactly — no class here defines testing(), so it falls through to the fallback.

The Type column is the point: it is the declared PHP type, so an enum-typed property names its enum here. Sensitive values print as ********.

env-settings:diff

What changes between environments

Resolves one class twice — once per environment — and marks every property that differs with a *. No SSH, no comparing two .env files by eye.

php artisan env-settings:diff "App\Settings\PaymentSettings" staging production
[ PaymentSettings ] — Comparing staging vs production
+------------------+----------+------------+
| Property         | staging  | production |
+------------------+----------+------------+
| mode *           | sandbox  | live       |
| currency         | USD      | USD        |
| retry_attempts * | 3        | 5          |
| webhook_url *    | ******** | ********   |
+------------------+----------+------------+
* = values differ between environments

Masked but still flagged. Both columns read ********, yet the row keeps its * — comparison happens before masking.

When nothing differs the legend is replaced by No differences found.

env-settings:check

A gate, not a report

Reports properties still sitting at their generated placeholder for a target environment — but only when another environment supplies a real value. The one command here that exits non-zero, so it works in CI as-is.

php artisan env-settings:check --env=production
php artisan env-settings:check
php artisan env-settings:check "App\Settings\AuthSettings"
incomplete exit 1
✗ App\Settings\AuthSettings
    domain      empty string, but set in development()
    timeout     0, but set in development()
complete exit 0
[ production ] — 5 settings
classes complete.

Full walkthrough — what counts as a placeholder, why an all-placeholder class reports as complete, and #[AllowEmpty].

💬

Leave the arguments off

All four share the same input trait, so anything you omit is asked for instead of erroring. Running env-settings:diff bare walks you through picking a class and two environments — which is exactly the sequence animated on the home page.

Full docs on GitHub Masking Enums The gate #[Environment] In tests Overrides Is this for you? Back to the demo