Env::load() reads its inputs from the environment and a .envless file, caches on disk and fills the process environment. Env::fetch() does none of that: you pass every input as an argument, it fetches and decrypts, and it returns a plain array. It is the PHP twin of @goenvless/env/edge.
use Envless\Env\Env;
function databaseUrl(string $token, string $key): string
{
$values = Env::fetch(token: $token, project: 'api', environment: 'production', key: $key);
return $values['DATABASE_URL'];
}Every call fetches again: there is no memo, no cache file and no write to $_ENV, $_SERVER or getenv(), and Env::get() does not see the values. Keep the array for as long as your function lives.
Options
| Option | Required | Purpose |
|---|---|---|
token | ✅ | An ev_sk_ machine key |
project | ✅ | The project slug |
environment | ✅ | The environment slug |
product | The product slug, when the project slug exists in more than one product | |
key | one of the two | The base64url raw workspace key. Checked first, so it wins when both are passed |
passphrase | one of the two | The workspace passphrase. The workspace is looked up over the API to derive the key |
workspaceId | Skips that lookup on the passphrase path | |
endpoint | Overrides the API base URL | |
httpClient | An Envless\Http\HttpClient to send the requests through, such as Envless\Http\Psr18HttpClient around Guzzle |
Each missing input is refused with a message that says what to pass:
Pass a machine key as token:. Env::fetch() reads no .envless file and no config to find one in.
Pass project: and environment:. Env::fetch() reads no .envless file to resolve them from.
Pass passphrase: or key:. Without one the values cannot be decrypted.
The workspace could not be resolved, so the passphrase cannot be turned into a key. Pass workspaceId: explicitly.An API failure throws LoadException with the API's own message, and a value the key cannot open throws Could not decrypt STRIPE_SECRET.
Bref and AWS Lambda
Lambda keeps a warm container alive between invocations and gives PHP a writable /tmp, so the ordinary Env::load() works there too: when the home folder is read-only, the cache moves to the system temp folder on its own and is reused while the container stays warm. Use Env::fetch() when the credentials come from a secret store at runtime rather than from environment variables:
use Envless\Env\Env;
return static function (): string {
$values = Env::fetch(
token: (string) getenv('ENVLESS_TOKEN'),
project: 'api',
environment: 'production',
key: (string) getenv('ENVLESS_KEY'),
);
return $values['PUBLIC_GREETING'] ?? 'Hello';
};Laravel Vapor
Vapor runs Laravel on Lambda, so the Laravel setup works unchanged: the guarded Env::load() in bootstrap/app.php, with ENVLESS_TOKEN and ENVLESS_KEY set as environment variables or secrets of the Vapor environment. The cache lands in /tmp and lasts as long as the warm container.
Many workspaces in one process
Because Env::fetch() keeps nothing, it is also how a multi-tenant app reads several environments side by side, one call per tenant with that tenant's machine key:
use Envless\Env\Env;
/**
* @param array{token: string, key: string, environment: string} $tenant
* @return array<string, string>
*/
function tenantValues(array $tenant): array
{
return Env::fetch(token: $tenant['token'], project: 'api', environment: $tenant['environment'], key: $tenant['key']);
}