PHP

Serverless and explicit loading

Env::fetch() loads with every input passed as an argument and touches nothing on disk or in the process environment, for Bref, Laravel Vapor, multi-tenant apps and anywhere the inputs are not in environment variables.

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.

php
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

OptionRequiredPurpose
token✅An ev_sk_ machine key
project✅The project slug
environment✅The environment slug
productThe product slug, when the project slug exists in more than one product
keyone of the twoThe base64url raw workspace key. Checked first, so it wins when both are passed
passphraseone of the twoThe workspace passphrase. The workspace is looked up over the API to derive the key
workspaceIdSkips that lookup on the passphrase path
endpointOverrides the API base URL
httpClientAn 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:

txt
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:

php
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:

php
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']);
}