MLC
MLC is the MonkeysLegion configuration layer: a tiny parser/loader for the human-friendly .mlc file format.
It gives you strongly-typed, immutable config objects without the weight of YAML or the rigidity of PHP arrays.
1 · Installation
composer require monkeyscloud/monkeyslegion-mlcThe package is pure PHP 8.4 – nothing else is pulled in.
2 · .mlc syntax at a glance
# comments start with #
app.name = "MonkeysLegion"
app.debug? = true # “?” makes the key optional
[database]
driver = "mysql"
host = env("DB_HOST", "127.0.0.1")
port = 3306
name = "monkeys_app"
user = env("DB_USER")
pass! = env("DB_PASS") # “!” marks as required – missing ⇒ exception
[cache.redis]
host = "localhost"
port = 6379Sections are declared with [section], nested via dot-notation.
Primitive types: string, int, float, bool, null.
Env helper: env(KEY, default?) pulls from $_ENV or putenv().
Guards:
key! → must exist after env/default merge.
key? → optional; missing keys resolve to null.
3 · Loading config in bootstrap
use MonkeysLegion\Mlc\Loader;
use MonkeysLegion\Mlc\Config;
// 1) point the loader at your directory
$loader = new Loader(base_path('config'));
// 2) load one or many files (*.mlc)
$raw = $loader->load(['app.mlc', 'database.mlc']);
// 3) wrap in an immutable Config object
$config = new Config($raw);
// 4) ask for values anywhere in your code
$dbHost = $config->get('database.host'); // "127.0.0.1"
$isDev = $config->bool('app.debug'); // trueConfig offers helpers for strict casts (string(), int(), array()), default fall-backs (->get('x', 'default')), and guarded retrieval (->require('app.name') throws if absent).
4 · Environment-specific overrides
Directory layout:
config/
├─ app.mlc
├─ database.mlc
└─ env/
├─ dev.mlc
└─ prod.mlc$env = $_ENV['APP_ENV'] ?? 'dev';
$raw = $loader->load(['app.mlc', 'database.mlc', "env/{$env}.mlc"]);
$config= new Config($raw);Later files override earlier keys, so env/prod.mlc can flip app.debug? = false or point Redis to a different host.
5 · Runtime reloading (CLI & tests)
$config = $config->merge($loader->load('feature-flags.mlc'));The original object stays untouched; you get a new instance with the extra layer applied—perfect for A/B tests or command-line overrides.
6 · Integration with DI
return [
MonkeysLegion\Mlc\Config::class => fn () => new Config(
(new Loader(base_path('config')))->load(['app.mlc', 'database.mlc'])
),
];Any service can now just type-hint Config.
7 · Parser & Loader internals (overview)
Parser – tokenises lines, resolves env(), casts primitives, returns nested arrays.
Loader – finds files, feeds them to the parser, merges results, detects duplicate keys.
Config – read-only wrapper with dot-notation access and merge/cloning helpers.
You rarely touch these classes directly—the façade methods above cover day-to-day needs.
8 · Roadmap
Include directive (@include other.mlc) for split configs
Hot-reload in DevServer—trigger browser refresh when config/*.mlc changes
Validation DSL—define allowable enum values right in the file (mode = enum("dark","light"))
Contributions welcome!
License
MIT © 2025 MonkeysCloud