Namespace HtmlPhp\. Both editions expose the identical API. Everything is
instance-based; nothing reads globals. Typical wiring is one call:
$engine = HtmlPhp\Engine::create($configArrayOrObject, $optionalContainerSetup);| Method | Description |
|---|---|
Engine::create(Config|array $config = [], ?callable $setup = null): self |
Builds config (arrays go through Config::fromArray), wires the container, runs $setup(Container) before any service instantiation |
render(string $name, array $vars = [], ?RenderOptions $o = null): string |
Renders a template resolved through templates.paths/namespaces (throws TemplateNotFoundException) |
renderFile(string $path, array $vars = [], ?RenderOptions $o = null): string |
Renders a host-provided path (size-guarded, SSI-anchored) |
renderString(string $source, array $vars = [], ?RenderOptions $o = null): string |
Renders inline/DB-sourced templates |
display(...) / displayString(...) |
echo variants |
processSsi(string $content, ?DocumentInfo $doc = null): string |
Standalone SSI pass (post content, option values, legacy pages) |
ssiVariables(?DocumentInfo $doc = null): array<string,string> |
Built-in SSI map (diagnostics/CLI) |
t / n / x / nx(...) |
Translation shortcuts (see TranslatorInterface) |
setLocale(string) / locale(): string |
Active locale |
loadTranslations(string $locale, ?string $domain = null): list<string> |
Force-loads configured i18n.paths; returns loaded files |
lint(string $nameOrPath): list<LintIssue> · lintString($src, $origin) · lintDirectory($dir): array<file, list<LintIssue>> |
Static template validation |
clearCache(): int |
Purges render cache + parse memo |
stats(): ?RenderStats |
Profiling of the most recent render |
config() container() renderer() locator() ssi() translator() filters() events() cache() logger() diagnostics() clock() linter() escaper() |
Service accessors (all lazy singletons) |
version(): string |
"5.0.0 (8.3 edition)" |
file, root, request (RequestContext), ssi, structure, autoEscape,
missingVar (enum), cache, ttl, locale, ssiVars. Also
RenderOptions::fromArray($v3StyleOptions) as a migration aid.
template, startedAt, durationMs, cacheHit, substitutions, loops, loopRows, conditionals, includes, sections, translations, ssiDirectives, outputBytes, peakMemoryKb, templates[] + toArray(); the 8.5 edition adds a computed
summary property hook. Emitted with the htmlphp.rendered event.
severity (error|warning|info), code, message, file, line,
context[]; format() → file:line SEVERITY [code] message; toArray().
Codes: unknown-tag, unclosed-tag, unbalanced-tag, orphan-mid, unknown-filter, filter-disabled, filter-arg-not-numeric (v5, warning), bad-expression, expressions-disabled (v5), unresolved-include, unresolved-extends, missing-reference, loop-range-too-large, loop-signal-outside-loop, trans-count-without-plural, trans-plural-without-count, trans-nested-tag, untranslated-message, unknown-ssi-directive, ssi-missing-expr, ssi-include-target, ssi-echo-var, ssi-set-var, ssi-bad-expr, ssi-exec-denied, template-unreadable.
Config::default(); Config::fromArray([...]); $config->merge([...]);
$config->withDebug(true); // + withSsi/withI18n/withCache/withTemplates/withSyntax
$config->toArray(); // round-trips through fromArrayGroups (each a final readonly class with fromArray/toArray/KEYS):
templates, syntax, ssi, i18n, cache, log, security, limits.
Unknown keys at any level throw ConfigException — typos fail fast.
Full key table: CONFIGURATION.md.
Enums: Config\MissingVarPolicy {Empty, Keep, Placeholder, Throw},
Config\ExecMode {Deny, AllowList, Delegate}, Config\SizeFormat {Abbrev, Bytes}, Config\CacheDriver {Null, Array, File, Apcu, WordPress},
Config\LogDriver {Null, Array, ErrorLog, File, Syslog, WordPress}.
factory(id, fn(Container)) (lazy, shared) · instance(id, $obj) ·
get/has/service<T>/ids/reset · Container::withDefaults(Config).
Service ids are the class/interface names: Config::class,
Contracts\CacheInterface::class, Log\LoggerInterface::class,
Event\Dispatcher::class, Diagnostics::class, Support\ClockInterface::class,
Html\Escaper::class, I18n\Formats::class, I18n\TranslatorInterface::class,
Template\{Filters, TemplateLocator, Renderer, Linter}::class,
Ssi\Processor::class, Engine::class.
Engine::create($config, function (Container $c): void {
$c->instance(Contracts\CacheInterface::class, new MyRedisCache());
$c->instance(Support\ClockInterface::class, new FrozenClock(1700000000));
$c->instance(Log\LoggerInterface::class, Log\Psr3Adapter::wrap($monolog));
$c->instance(I18n\TranslatorInterface::class, new MyDbTranslator());
});new Scope($rootVars); push/pop/with/get/has/set/find/all/depth.
find('a.b.c') returns [found, value] walking arrays, ArrayAccess,
public props and get*/is*/has* accessors. No $GLOBALS fallback — ever.
Static accessors (v5), used by the expression evaluator and safe to call from host code:
Scope::step(mixed $value, string $path): array{bool, mixed}— walks a dotted path through arrays /ArrayAccess/ public properties and zero-arg accessors (getX/isX/hasX). Read-only.Scope::index(mixed $value, mixed $key): array{bool, mixed}— one element by a dynamic key. Arrays,ArrayAccessand UTF-8 string offsets only;int/stringkeys only (≤ 256 chars, no null bytes); plain objects are never indexable by dynamic key. Always[found, value], never a warning.Substitution::splitFilters(),Substitution::splitExpressionPayload()(quote- and bracket-aware),Substitution::splitArguments()andSubstitution::parseSegments()are public statics for host tooling.
RequestContext::fromServer($_SERVER) (edge) · ::cli($cwd) ·
http(name) for HTTP_*. Fields: documentRoot, scriptName, requestUri, documentName, documentUri, queryString, method, remoteAddr, userAgent, acceptLanguage, referer, server.
Input::all() / Input::source('get|post|cookie|request') — recursively
htmlspecialchars-encoded copies; superglobals are never modified. The
only sanctioned superglobal reader besides the WP adapters.
record(code, message, context) · all() byCode(code) count(code='') last() clear() clean(). Capped at limits.max_diagnostics (100). Forwards
to the logger (when log.forward_diagnostics) and fires htmlphp.error.
Codes: missing-var, ssi-include-failed, ssi-include-cycle, ssi-limit-reached, ssi-exec-denied, ssi-exec-failed, ssi-expr-error, ssi-unknown-directive, filter-unknown, expr-invalid, expr-disabled, regex-failed, catalog-parse, cache-io, loop-guard, template-lint, wp-bridge.
WordPress-hook shaped: on(tag, callable, priority=10): Closure(unsub) ·
off(tag, ?priority) · dispatch(tag, ...args) · filter(tag, $value, ...args): mixed (null returns keep the previous value; recursion-capped) ·
has/tags/reset.
Engine tags: htmlphp.render.before, htmlphp.render (filter),
htmlphp.render.after, htmlphp.rendered (RenderStats), htmlphp.error,
htmlphp.translate (filter), htmlphp.translate.miss,
htmlphp.filter.apply, htmlphp.ssi.builtins (filter),
htmlphp.ssi.include_path (filter), htmlphp.ssi.echo (filter).
interface Contracts\CacheInterface { get set has delete clear(): int }
interface Log\LoggerInterface { log debug info notice warning error critical alert emergency }Implementations: Cache\{FileCache, ApcuCache, ArrayCache, NullCache, Psr16Adapter} + WordPress\WpCache; Log\{FileLogger, ErrorLogLogger, SyslogLogger, ArrayLogger, NullLogger, Psr3Adapter} + WordPress\WpLogger.
Factories: Cache\CacheFactory::create(CacheConfig),
Log\LoggerFactory::create(LogConfig) / ::wrap($psr3).
FileCache shards by key hash, writes atomically, GCs probabilistically
(~1 % of writes), and drops a deny-all .htaccess + index.html into the
cache dir (cache.harden_directory).
Ssi\Processor (process, processWithContext, variables,
directives(): DirectiveRegistry, lastProcessed()) ·
Ssi\DocumentInfo(file, root, request, vars) · Ssi\SsiContext (state,
budgets, resolvePath/resolveExecutable/variable/resolve) ·
Ssi\DirectiveInterface {name, render} · Ssi\Expression (mod_include
grammar) · Ssi\Exec (policies) · Ssi\{Attributes, TimeFormat, SizeFormat, Builtins, Scanner(internal)}.
I18n\TranslatorInterface · I18n\Translator (load, register,
loadConfigured, catalogue(s), hasCatalogue, stats, reset, locale,
setLocale, availableLocales, negotiate, fallbackChain, t/n/x/nx,
interpolate static) · I18n\Catalog (load po/mo/json/php, fromPo,
fromMo, fromArray, mergeFrom, get/getPlural/has/ids/headers/count/ pluralForms) · I18n\PluralForms (parse, select, count, MAX_FORMS=6)
· I18n\Locale (normalize, language, parseAcceptLanguage,
negotiate) · I18n\Formats (number/date/time/datetime/ago) ·
I18n\Extractor (scan, scanDirectory, entries, dynamicHits,
toPo) · I18n\Auditor (audit, format).
Template\{Renderer, TreeRenderer, TagParser, Node, Substitution, Filters, Expression, TemplateLocator, Linter, LintIssue, RenderOptions, RenderStats, RenderContext, LoopSignal} — see ARCHITECTURE.md for the pipeline.
Support\Str (stringify, numericValue, round/cleanRound/number/divide,
power/sqrt/accumulate (v5, INF/NAN-safe, iteration-capped),
truncate, slugify, keepWordChars, normalizeEntities, formatSize,
isValidVariableName, sanitizeRecursive, upper/lower/ucfirst/words/length/substr)
· Support\Pcre (throwing wrappers; match/matchAll degrade to no-match) ·
Support\{ClockInterface, SystemClock, FrozenClock} ·
Io\{Files, AtomicWriter, PathGuard} · Html\Escaper (html/attr/url/json/
js/css/byStrategy/sanitizeArray; subclassable, container-replaceable) ·
Html\Cleaner (lcTags, normalize, cleanTag, cleanHtml with injected
allow-list, trimSpaces).
HtmlPhpException (context map, withContext(), describe())
├─ ConfigException ├─ ContainerException ├─ IoException
├─ CacheException ├─ RegexException ├─ SsiException
├─ I18nException └─ TemplateException
├─ TemplateNotFoundException
└─ TemplateSyntaxException
WordPress\Bridge (boot/engine/booted/reset) · TemplateLoader
(locate/render/renderPart) · Shortcodes · WpCache · WpLogger ·
AdminPage · Cli · Mailer · Maintenance\{Nonces, Options, Transients, Notices, Db, Cron, Logs, SystemInfo, Updates, Health, Assets, Rest}.
Details: WORDPRESS.md.