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

Env Laravel Package

oscarotero/env

oscarotero/env is a simple PHP library to read environment variables and convert them to typed values (bool, int, float, arrays, etc.), with support for .env files, defaults, and nested variable expansion. Lightweight and dependency-free alternative to phpdotenv.

Deep Wiki
Context7

Getting Started

oscarotero/env is a single-class, zero-dependency reader for process environment variables with light type coercion. It is not a .env file loader — it reads what is already in the process environment (getenv() / $_ENV / $_SERVER).

Minimal steps:

composer require oscarotero/env
require __DIR__ . '/vendor/autoload.php';

use Env\Env;

$debug = Env::get('APP_DEBUG', false);   // bool
$port  = Env::get('PORT', 8080);         // int
$name  = Env::get('APP_NAME', 'app');    // string

Where to look first:

  1. README.md — the whole API fits on one screen.
  2. src/Env.php — ~100 lines; worth skimming to confirm the exact type-constant names and the auto-conversion rules before you rely on them.
  3. Your bootstrapping entry point (public/index.php, artisan, a CLI script) — this is where environment variables actually reach PHP, and where Env::get() belongs.

First use case: a framework-agnostic config.php that returns a typed array. Everything downstream consumes the array, not the environment, so the rest of the codebase is testable and free of getenv() calls.

Implementation Patterns

Config-as-a-boundary. Put every Env::get() call in one or a handful of config files. Convert once, at boot, then pass typed values around. This mirrors Laravel's "only use env() inside config/" convention and keeps environment coupling to one layer.

// config/database.php
return [
    'host'     => Env::get('DB_HOST', '127.0.0.1'),
    'port'     => Env::get('DB_PORT', 3306),
    'database' => Env::get('DB_DATABASE', 'app'),
    'debug'    => Env::get('DB_DEBUG', false),
];

Explicit types over implicit coercion. Auto-conversion of strings like "true", "false", "null", and numerics is convenient but implicit. For anything security- or correctness-sensitive (feature flags, timeouts, pool sizes), force the type explicitly using the package's type constants — e.g. Env::get('WORKERS', null, Env::TYPE_INT) — and treat a null result as a configuration error rather than relying on a default. Check src/Env.php for the exact constant names in your version.

Fail fast for required values. The library returns the default (usually null) for missing keys and does not validate. Wrap it:

function required(string $key): string
{
    $value = Env::get($key);
    if ($value === null || $value === '') {
        throw new RuntimeException("Missing required env var: {$key}");
    }
    return $value;
}

Laravel integration. Laravel's own env() already coerces true/false/null/empty, so this package earns its place mainly in (a) non-Laravel or framework-agnostic packages, (b) code shared between Laravel and standalone CLI tools, and (c) places where you want a stricter, predictable coercion with a documented default. Inside Laravel, still confine calls to config/*.php and re-run php artisan config:cache after changing your reader logic.

Docker / CI workflow. Define variables in docker-compose.yml, a Kubernetes Secret, or CI settings; let the package do the typing inside the container. This keeps a clean split: infrastructure owns where values come from, PHP owns what type they are.

Testing. Set values before each test, and clean up afterwards:

setUp():    putenv('DB_PORT=5433'); $_ENV['DB_PORT'] = '5433';
tearDown(): putenv('DB_PORT'); unset($_ENV['DB_PORT']);

For anything larger, wrap Env::get() behind your own Config object and inject that — the static API is awkward to mock.

Gotchas and Tips

  • It does not read .env files. Pair it with vlucas/phpdotenv, symfony/dotenv, Laravel's bootstrap, or real container/host environment variables. A common mistake is installing this package expecting .env parsing.
  • getenv() vs $_ENV vs $_SERVER. Different SAPIs populate different superglobals. PHP-FPM with clear_env = yes (a frequent default) strips the environment entirely — you must pass variables via env[...] in the pool config or read from $_SERVER. Verify with a quick var_dump(getenv('FOO'), $_ENV['FOO'] ?? null) in the actual runtime, not just your shell.
  • Coercion edge cases. Watch "0" becoming 0 (falsy), empty string vs. null, whitespace around values (" true "), and values like "yes"/"on" that are not converted to booleans. Keep env values canonical: true/false, plain integers, no quotes.
  • Forced type vs. default ambiguity. The second argument serves as a default; combining a default and a forced type in one call can be surprising. When in doubt, read the value as a string and cast explicitly in your own code — it's one extra line and removes all doubt.
  • Laravel config caching. Once config:cache runs, config/*.php is not re-evaluated, so changing an environment variable will not take effect on the next request even though Env::get() would return the new value. Any env-driven logic must live in config files, never in controllers or services.
  • Case sensitivity. Environment variable names are effectively case-sensitive on Linux and case-insensitive on Windows. Stick to UPPER_SNAKE_CASE to avoid surprises.
  • Static API is untestable in isolation. There is no DI or mocking hook. If your test suite needs to swap environment values per test, build a thin adapter (interface Config { public function get(string $key, mixed $default = null): mixed; }) and bind it once at boot.
  • Don't log values. Debugging env problems usually means dumping the variable — easy to leak secrets into logs. Log the key name and whether it was present, not the value.
  • Secrets discipline. Use .env locally (git-ignored) and real secrets managers in production. The library will happily return a credential; keeping it out of source control and logs is on you.
  • Extension points are minimal by design. There's no plugin system or custom coercer registration. Anything beyond string/bool/int/float/null belongs in a wrapper function in your own config layer — that is the intended extension point.
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.
elsayed85/laravel-api-exceptions
ouhssini/laravel-demo-mode
daworks/ncloud-outbound-mailer-driver
gp247/cms
ignibyte/aic-gates
nexa-merchant/blog
novasa/laravel-language-center
opencage/geocode
adolfoholzer/parameters
livenetworks/ln-starter
shitoudev/permissionmanager
johannesclimacus/laravel-tui
hocvt/seotools
vitalybaev/sypexgeo
amphibee/themosis-ignition
gito-me/fast-excel
frankyso/laravel-ipaymu
geolize-studio/laravel-chile
boomerangui/chat
cgv/localized-resource