Clone this demo locally from
github.com/HPWebdeveloper/laravel-env-setting-demo,
then change APP_ENV in your .env file
(e.g. to staging or production),
run php artisan config:clear, and refresh this page to see every value change automatically.
Current APP_ENV:
production
| provider | openai |
| text_model | gpt-4o |
| embeddings_model | text-embedding-3-large |
| max_tokens | 8000 |
| temperature | 0.2 |
| mode | live |
| currency | USD |
| retry_attempts | 5 |
| webhook_url | https://app.example.com/webhooks/payments |
| sms_provider | vonage |
| sms_from | +15559876543 |
| default_channel | sms |
| rate_limit_per_minute | 200 |
| sandbox_mode | false |
| billing_service_url | https://billing.internal |
| inventory_service_url | https://inventory.internal |
| notification_service_url | https://notify.internal |
| timeout | 10 |
| retry_attempts | 5 |
What is this? Instead of accessing each settings class individually
(AiSettings,
PaymentSettings, etc.),
you can create a single root settings object that groups them all together.
AppSettings is a settings class whose properties are other settings classes.
When it resolves for the current environment, it calls each sub-setting's environment method internally — so you get one object that holds the full configuration tree.
Usage:
envSettings(AppSettings::class)->ai->text_model
or
envSettings(AppSettings::class)->payment->mode
— access any nested setting from a single entry point.
Full JSON output of the composed settings tree for the current production environment:
{
"ai": {
"provider": "openai",
"text_model": "gpt-4o",
"embeddings_model": "text-embedding-3-large",
"max_tokens": 8000,
"temperature": 0.2
},
"payment": {
"mode": "live",
"currency": "USD",
"retry_attempts": 5,
"webhook_url": "https:\/\/app.example.com\/webhooks\/payments"
},
"notification": {
"sms_provider": "vonage",
"sms_from": "+15559876543",
"default_channel": "sms",
"rate_limit_per_minute": 200,
"sandbox_mode": false
},
"external_api": {
"billing_service_url": "https:\/\/billing.internal",
"inventory_service_url": "https:\/\/inventory.internal",
"notification_service_url": "https:\/\/notify.internal",
"timeout": 10,
"retry_attempts": 5
}
}
What does this prove? There are two ways to get a settings instance in Laravel:
envSettings(AiSettings::class)public function __invoke(AiSettings $ai) in a controllerBecause this package registers each settings class as a singleton in Laravel's service container, both approaches return the exact same object in memory — not a copy, not a new instance, but the same one.
This means you can freely mix both styles in your application without worrying about inconsistent state or wasted memory.
envSettings(AiSettings::class) and a type-hinted AiSettings injection resolve to the
same singleton instance:
yes — same instance