dkm / dotenv-autoload
Auto-loads .env then .env.local at Composer autoload time. No plugin, no config.
Requires
- php: >=8.1
- composer-runtime-api: ^2.1
- symfony/dotenv: ^6.4 || ^7.0
This package is auto-updated.
Last update: 2026-08-19 10:45:22 UTC
README
Auto-loads .env then .env.local into the environment at Composer autoload
time. It replaces helhum/dotenv-connector + a custom adapter package with a
single plain library — no Composer plugin, no extra config, no
allow-plugins entry, no generated include file.
Install
composer require dkm/dotenv-autoload
That's the whole integration. The package's autoload.files entry runs
src/load.php whenever vendor/autoload.php is loaded.
Behaviour
- Loads
<project-root>/.env, then<project-root>/.env.local..envholds shared defaults;.env.localcarries per-instance overrides. - Project root is resolved via
Composer\InstalledVersions::getRootPackage(), so it works even when this package is installed as a symlinked path repo (wheredirname(__DIR__, N)would point intopackages/...). - Uses Symfony Dotenv
load(): a variable already set in the real environment (or in.env) is not overwritten by.env.local. SetDOTENV_OVERRIDE=1to switch tooverload()so.env.localwins. - Skips entirely when
APP_ENVis already set in the environment.
TYPO3_CONTEXT consistency (CLI vs web)
The main reason to load .env this way is a single source of truth for env vars —
including TYPO3_CONTEXT — across both the web SAPI and the typo3 CLI binary. Because
src/load.php runs from vendor/autoload.php, which both a web request and the CLI require,
the same .env values are read on both sides. That prevents the classic split where a site
behaves as one environment in the browser and another on the command line (so deploy tooling,
crons, and the live site disagree about whether the site is live).
Caveat — a server-injected value still wins. load() is non-overwriting, so a
TYPO3_CONTEXT injected by php-fpm/nginx (fastcgi_param, or a pool env[TYPO3_CONTEXT])
takes precedence for web requests, while .env still wins for CLI (which never sees that
server var). That re-introduces the exact split this package is meant to avoid — e.g. web reads
Production/Live while CLI reads Production/Staging.
To keep a single source of truth:
- Preferred: declare
TYPO3_CONTEXTin.env/.env.localand remove any server-side injection. Then CLI and web agree automatically. - If the server-injected value must stay authoritative, set
DOTENV_OVERRIDE=1so.envwins everywhere — but that is a blunt instrument (it flips precedence for every var).
Silent-default trap: if nothing sets TYPO3_CONTEXT in a given context (no .env value and
no inherited env var), TYPO3 falls back to bare Production. On the CLI that can make a non-live
instance look live to command-line tooling. Declaring it in .env/.env.local avoids this,
since this loader then supplies it to both SAPIs.
Tip:
dkm/typo3-robots-guardactively surfaces such a split — itsrobots:verifycommand and backend badge warn when the CLI/web contexts (or a live context in a non-live project folder) don't line up.
Boundary (important)
Env vars are exposed when vendor/autoload.php is loaded — i.e. on web requests
and in CLI subprocesses (e.g. the typo3 binary invoked from Composer
scripts). They are not exposed inline inside the running Composer process.
So this is safe for:
- application runtime, and
- Composer scripts that shell out to a binary (
typo3 ...).
It is not sufficient for:
- a Composer plugin, or
- an inline PHP-callback Composer script (
"Vendor\\Class::method"),
that reads these env vars during composer install/update. If you ever add one
of those and it needs .env values, keep helhum/dotenv-connector for that
project instead.