The Container Lifecycle
This library's headline feature is compilation: the expensive work of reading your .ctn files and resolving the dependency graph happens once, at build time, and produces a plain PHP class. At runtime you just include that class and resolve services from it — there is almost no overhead.
Understanding this pipeline explains why the API is shaped the way it is.
The pipeline
app.ctn (source text)
│
▼
ContainerLexer tokenizes the .ctn source
│
▼
Parser builds an AST of Nodes
│
▼
ContainerInterpreter walks the AST, fills a…
│
▼
ContainerNamespace the "pot" of parsed parameters + service definitions
│ (importNamespace)
▼
ContainerBuilder code-generates a Container subclass…
│ (generate)
▼
Generated PHP class one resolver method per service, written to cache/
│ (require + new)
▼
Container instance fast runtime resolution — get(), has(), …Everything above the generated class is build-time and runs only when the cache is (re)built. Everything below is runtime.
Who drives it
For the recommended setup you never touch the lexer, parser or interpreter directly. The ContainerFactory orchestrates the whole thing:
$factory = new \ClanCats\Container\ContainerFactory(__DIR__ . '/cache');
$container = $factory->create('AppContainer', function($builder) {
$namespace = new \ClanCats\Container\ContainerNamespace();
$namespace->parse(__DIR__ . '/app.ctn'); // source → namespace
$builder->importNamespace($namespace); // namespace → builder
});create() does the following:
- If a class named
AppContaineris already loaded, it returns a new instance immediately. - Otherwise it looks for a cached file (
cache/AppContainer.php). - If that file is missing — or debug mode is on — it runs your callback, code-generates the class and writes it to the cache directory.
- It
requires the cache file and returnsnew AppContainer($initialParameters).
So the parsing/building steps only ever run when the cache file is absent.
Debug mode
Because create() rebuilds only when the cache file is missing, editing an .ctn file during development would not take effect until you delete the cache. Debug mode forces a rebuild on every call:
$factory = new \ClanCats\Container\ContainerFactory(__DIR__ . '/cache', true); // debug onTurn it off in production so the cached class is reused.
Where to go next
- Choosing an Implementation — compiled vs. dynamic vs. custom build.
- Using the Container — the runtime API that is identical across all implementations.
- Container Files — the
.ctnsyntax that feeds this pipeline.
