How the PHP-DTS Custom Template Engine Parses and Renders .htm Template Files

The PHP-DTS template engine compiles custom .htm syntax into executable PHP by transforming tags like {if}, {loop}, and {$var} into native PHP constructs, caching the result in gamedata/cache/ for direct inclusion on subsequent requests.

The amarillonmc/phpdts repository implements a lightweight, self-contained template system that avoids external dependencies. This PHP-DTS custom template engine processes raw .htm files through a two-stage pipeline—first locating and validating templates, then parsing custom markup into standard PHP code that the server executes directly.

Template Engine Architecture

The system centers on two core functions defined in the include/ directory. The template() function in include/global.func.php serves as the entry point, handling template selection and cache management. When compilation is required, it delegates to parse_template() in include/template.func.php, which performs the actual syntax transformation using regular expressions and callbacks.

Step-by-Step Parsing Flow

Template Resolution and Cache Validation

When a controller calls template($file, $templateid, $tpldir), the engine first resolves the absolute path to the source .htm file (e.g., ./templates/nouveau/index.htm according to the phpdts source). It then constructs a compiled cache path under gamedata/cache/ that incorporates the template ID to support multiple skins. If the cached PHP file is missing or older than the source template, the engine triggers a full recompile before proceeding.

Syntax Translation and Normalization

Inside parse_template(), the raw template content undergoes a series of ordered transformations to convert custom tags into native PHP constructs:

  • Language localization: {lang KEY} becomes the corresponding string from the global $lang array via callback replacement (lines 29‑30 of include/template.func.php).
  • Variable output: {$var} or { $array['key'] } transforms into <?= $var ?> with normalized array syntax (lines 34‑35).
  • Expression evaluation: {eval PHP_CODE} rewrites to <?php PHP_CODE ?>, while {echo EXPRESSION} becomes <?php echo EXPRESSION; ?> (lines 45‑46 and 48‑49).
  • Control structures: {if CONDITION}, {elseif CONDITION}, {else}, and {/if} map directly to standard PHP conditional blocks (lines 51‑57).
  • Loop constructs: Both {loop $array $item} and {loop $array $key $value} generate foreach loops (lines 57‑63).
  • Template inclusion: {template other} recursively includes <? include template('other'); ?> (lines 43‑44).
  • Constants: {CONST} outputs via <?= CONST ?> (line 68).

The engine also strips unnecessary line breaks and tabs (lines 27‑28) and expands short <? tags to full <?php syntax for compatibility (lines 69‑72).

File Compilation and Inclusion

Finally, the transformed PHP string is written to the cache path (e.g., gamedata/cache/index_2.php). Control returns to template(), which includes the compiled file via include $compiled_file; (lines 114‑122 of include/global.func.php), executing the embedded PHP and streaming the resulting HTML to the browser.

Core Source Files and Functions

The template system relies on these specific implementation files:

  • include/global.func.php: Contains the template() dispatcher (starting at line 90) that manages template directory resolution and cache validation.
  • include/template.func.php: Houses parse_template() (lines 8‑72) which executes the regex-based parsing logic.
  • templates/default/ and templates/nouveau/: Directories containing the raw .htm source files for different skins.
  • gamedata/cache/: Runtime directory storing compiled PHP versions of templates (e.g., index_2.php for template ID 2).

Practical Implementation Example

The following pattern demonstrates typical usage within a page controller:

define('IN_GAME', true);
require './include/global.func.php';

// Render using the "nouveau" skin (template ID 2)
include template('index', 2, './templates/nouveau');

This sequence:

  1. Locates ./templates/nouveau/index.htm.
  2. Validates or creates gamedata/cache/index_2.php.
  3. Includes the compiled PHP file, executing embedded foreach and if statements.
  4. Streams the resulting HTML to the client.

Summary

  • The engine uses two-stage processing: template() for orchestration and parse_template() for syntax transformation.
  • Cache-first architecture stores compiled PHP in gamedata/cache/ to eliminate parsing overhead on repeat requests.
  • Custom tag syntax including {lang}, {loop}, {if}, and {template} converts to native PHP constructs via regex replacement.
  • Recursive inclusion supports modular template design through the {template} tag.
  • All logic resides in include/global.func.php and include/template.func.php, making the system lightweight and portable.

Frequently Asked Questions

Where does the PHP-DTS template engine store compiled templates?

Compiled templates are stored as PHP files in the gamedata/cache/ directory. The filename includes the template ID (e.g., index_2.php for template ID 2), allowing multiple skin variants to coexist without collision.

How does the engine handle language localization in templates?

The parser recognizes {lang KEY} syntax and replaces it with the corresponding value from the global $lang array via a callback function. This occurs during the compilation phase in parse_template() at lines 29‑30 of include/template.func.php.

Can I use PHP code directly inside .htm template files?

Yes. The {eval PHP_CODE} tag executes arbitrary PHP during compilation, converting to <?php PHP_CODE ?>. For simple output, use {echo EXPRESSION} which becomes <?php echo EXPRESSION; ?>. Both tags are processed before the final compiled file is written to disk.

What happens if I modify a source .htm file after it has been compiled?

The template() function in include/global.func.php compares timestamps between the source .htm file and the cached PHP version. If the source is newer, it automatically invokes parse_template() to regenerate the compiled file before inclusion.

Have a question about this repo?

These articles cover the highlights, but your codebase questions are specific. Give your agent direct access to the source. Share this with your agent to get started:

Share the following with your agent to get started:
curl -s "https://instagit.com/install.md"

Works with
Claude Codex Cursor VS Code OpenClaw Any MCP Client

Maintain an open-source project? Get it listed too →