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

Laravel Env Polyfill Laravel Package

phpexperts/laravel-env-polyfill

A lightweight polyfill that brings Laravel's env() helper and .env file loading to any PHP project. Read environment variables with Laravel-style syntax and sensible type casting, no framework required.

View on GitHub
Deep Wiki
Context7

Getting Started

  1. composer require phpexperts/laravel-env-polyfill
  2. Open the package's composer.json first. The interesting bits are autoload.files (that's where the global env() helper gets registered, which means it exists as soon as vendor/autoload.php runs) and require (it will pull in vlucas/phpdotenv — note which major version, because the v2 Dotenv::load() API and the v3+ Dotenv::createImmutable()->load() API are not interchangeable).
  3. Skim src/. There are usually only two things in a package like this: a copy of Laravel's pre-5.8 env() helper and a thin loader that points Dotenv at your .env file. Find out whether the loader is invoked automatically or whether you must call it (e.g. from a bootstrap file) — that single detail determines your entry-point boilerplate.
  4. Create .env at the project root (copy from .env.example) and add both to .gitignore.
  5. First use case — a plain PHP CLI script or legacy app entry point:
<?php
require __DIR__ . '/vendor/autoload.php';
// plus whatever bootstrap call the package requires to load .env

$dsn = sprintf(
    'mysql:host=%s;port=%s;dbname=%s',
    env('DB_HOST', '127.0.0.1'),
    env('DB_PORT', '3306'),
    env('DB_DATABASE')
);

That's the whole value proposition: env('KEY', $default) in a codebase that has no Illuminate\Foundation\Application.

Implementation Patterns

Bootstrap once, read everywhere else. Call the loader in exactly one place (front controller, CLI entry, PHPUnit bootstrap.php, cron wrapper) and nowhere else. If the package doesn't auto-load, write a tiny bootstrap.php that requires the autoloader and then loads .env; have every entry point require that file.

Convert to a config array early. Don't sprinkle env() calls through business logic — it's a getenv()/$_ENV lookup every time, and it makes defaults impossible to reason about. Do this instead:

// config.php
return [
    'db' => [
        'host'     => env('DB_HOST', '127.0.0.1'),
        'port'     => (int) env('DB_PORT', 3306),
        'database' => env('DB_DATABASE'),
        'password' => env('DB_PASSWORD', ''),
    ],
    'debug' => (bool) env('APP_DEBUG', false),
];

Then $config = require 'config.php'; once at boot and pass it down. This mirrors Laravel's own "never call env() outside config files" guidance and is the single highest-leverage habit with this package.

Cast explicitly. The helper returns strings (with a few magic conversions — see Gotchas). (int), (bool), filter_var(..., FILTER_VALIDATE_BOOLEAN) for anything non-string.

Per-environment files. A common pre-5.8 pattern is loading .env.{APP_ENV} on top of .env, or picking the file based on a --env CLI argument / APP_ENV shell variable. Do that in your bootstrap, not in application code.

Tests. Load .env.testing in phpunit.xml's bootstrap (or set the variables via <php><env name="..." value="..."/></php>), and rely on the immutable behavior of Dotenv so real environment variables win over the file. Never let a test read the developer's local .env — it's a flaky-test factory.

Migration shim. If the project is heading toward Laravel, keep all env() calls confined to config/*.php-style files so you can move the files into a real Laravel app and delete the polyfill with zero application-code changes.

Gotchas and Tips

  • License is NOASSERTION. Before shipping this in anything commercial, read the repo's LICENSE/composer.json license field and confirm terms. With 5 stars, 0 dependents and one maintainer, you're the QA department.
  • Global function collision. The package defines a global env(). If the project ever pulls in laravel/framework or another polyfill that also defines it, you get a fatal "cannot redeclare function". Defensive move: fork and wrap the definition in if (!function_exists('env')), and remove the package the moment you adopt Laravel itself.
  • This is a convenience wrapper, not magic. The real work is done by vlucas/phpdotenv. If the package's loader fights you or its phpdotenv constraint pins you to an old version, delete it and call Dotenv::createImmutable(__DIR__)->safeLoad() directly — you lose maybe ten lines of code and gain control over the dependency.
  • Magic string casting. Laravel's pre-5.8 helper converts true/(true)/false/(false)/null/(null)/empty/(empty) from the raw string to native values. That means env('X', 'true') returns the boolean true, not 'true'. To get a literal string "true", quote it in .env (X="true"). This bites people reading feature-flag values.
  • null default is ambiguous. env('MISSING') and env('MISSING', null) are indistinguishable from deliberately-unset configuration. Use a sentinel default or a required helper (env('DB_PASSWORD') ?? throw new RuntimeException(...)) for values that must exist.
  • Precedence: real environment beats .env. Dotenv (in immutable mode) does not overwrite variables already set in $_ENV/$_SERVER/getenv(). That's usually what you want in containers, but it means a stale export DB_HOST=... in your shell silently shadows .env. If debugging "my edit did nothing", check getenv('DB_HOST') first.
  • Path resolution. Most failures are the loader looking in the wrong directory — .env paths are typically resolved against the current working directory, not the script's directory. Always pass an absolute path (__DIR__) in your bootstrap, especially under cron, PHP-FPM, or when the script is invoked from another directory.
  • Quoting in .env. Values with spaces, #, or = need quotes; unquoted # starts a comment mid-line. Multi-line values need double quotes. Validate on first run with a var_dump($_ENV) in dev.
  • No config caching exists here. The 5.8 change that broke env() with php artisan config:cache doesn't apply, but the mirror-image problem does: every env() call is a lookup, and your .env is parsed on every request. On a hot path (or a high-traffic PHP-FPM app) that's real overhead — another reason to convert to an array at boot, or generate a cached config.php in your deploy step.
  • Debugging checklist when env() returns null: (1) did vendor/autoload.php run before the call? (2) did the loader actually execute? (3) is the .env path absolute and readable? (4) is the key spelled exactly as in the file? (5) does var_dump($_ENV, $_SERVER) show it? Five questions that cover 95% of issues.
  • Extension point: because config is just a PHP array, you can layer sources — .env → OS environment → config/local.php (gitignored) — by merging arrays in your bootstrap. That gives you the escape hatch the polyfill itself doesn't offer.
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.
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
uni-method/symfony-lib