Core

Configuration

Lunaris keeps configuration in two places: a .env file for secrets and environment values, and a single PHP array in config/vars.php for everything else.

The .env file

Environment variables are loaded at boot with vlucas/phpdotenv in immutable mode. Keys are read through the env() helper — never through $_ENV or getenv() directly.

APP_KEY=def0000042cec0...   # Defuse ASCII-safe key (php lunar key:generate)
APP_NAME="Lunaris"
APP_URL=http://lunaris

config/vars.php

The central configuration file returns an array. Values may be closures, which are evaluated lazily when read — this is how config values wrap env() calls without paying for them on every request.

<?php

return [
    "app" => [
        "key" => fn() => env("APP_KEY", ""),
        "version" => fn() => env("APP_VERSION", "1.0.0"),
        "name" => fn() => env("APP_NAME", "Lunaris"),
    ],
    "errors" => [
        "notfound" => fn() => env("ERROR_NOT_FOUND", null),
        "forbidden" => fn() => env("ERROR_FORBIDDEN", null),
        "exception" => fn() => env("ERROR_EXCEPTION", null)
    ],
];

Reading configuration

Config values are read with dot notation through the config() helper:

config("app.name");        // "Lunaris" (from APP_NAME or default)
config("app.key");         // the APP_KEY value
config("errors.notfound"); // custom 404 page, or null

If a value is null, or the key path doesn’t exist, the default is returned:

config("app.missing", "fallback"); // "fallback"

The env() helper

env("APP_NAME", "Lunaris"); // value of APP_NAME, or "Lunaris" if unset/empty
Add your own keys

Drop a new entry into config/vars.php — keep wrapping env() in a closure so the value stays lazy: "stripe" => ["key" => fn() => env("STRIPE_KEY")], then read it with config("stripe.key").

Global helpers

All helpers live in system/funcs.php and are autoloaded globally:

HelperDescription
env($key, $default)Read an environment variable (empty/unset → $default).
config($key, $default)Read a config value with dot notation.
path() / base_path($path)The registered project root / a root-anchored path.
server()Origin URL scheme://host from a validated HTTP_HOST; honors X-Forwarded-Proto.
asset($path)Full URL to a file under public/.
url()Fully-qualified URL of the current request.
response()A new System\Http\Response instance.
route($name, $params)Generate a URL from a named route (or the current route name with no args).
route_is($route) / route_in([...])Current-route checks.
notfound($msg) / forbidden($msg) / error($msg)Throw the matching LunarException.
csrf_field($name)Hidden input carrying the CSRF token (for forms).
isfile($value)True if $value is a valid HTTP upload.

Helper examples

asset("logo.png");          // http://localhost:8080/logo.png
url();                      // http://localhost:8080/current/path
base_path("config");        // <project root>/config

// validated, trusted origin only
server();                   // "http://localhost:8080"
Security note

server() only trusts the host if it matches a hostname regex, and only honours X-Forwarded-Proto when it is literally http or https. Don’t build origin URLs from raw headers yourself.

Part of the Lunaris documentation · Source on Codeberg · MIT License