Star Template Engine - Documentation

Overview

Star is a lightweight, fast PHP template engine with support for template inheritance, includes, loops, conditionals, and automatic escaping. It compiles templates to pure PHP for optimal performance.

Table of Contents

  1. Installation
  2. Basic Usage
  3. Template Syntax
  4. Template Inheritance
  5. Variables
  6. Control Structures
  7. Includes
  8. Escaping and Raw Output
  9. Caching
  10. API Reference

Installation

Simply include the star.php file in your project:

<?php
require 'star.php';

Basic Usage

Rendering a Template

<?php
require 'star.php';

// Define your context (data)
$ctx = [
    'title' => 'My Page',
    'user' => [
        'name' => 'Alice',
        'age' => 30
    ],
    'items' => ['apple', 'banana', 'cherry']
];

// Render the template
echo star_render_template(
    'page.tpl',              // Template file (relative to templates folder)
    $ctx,                    // Context data
    './templates',           // Templates directory (optional, defaults to __DIR__.'/templates')
    './cache'                // Cache directory (optional, defaults to __DIR__.'/cache')
);

Template Syntax

Comments

Templates use standard HTML comments:

<!-- This is a comment -->

Whitespace Control

Use hyphens to trim whitespace around template tags:

{{- variable -}}       <!-- Trim whitespace before and after -->
{%- if condition -%}   <!-- Trim whitespace before and after -->

Template Inheritance

Base Template (layout.tpl)

<!doctype html>
<html>
<head>
  <title>{% block title %}Default Title{% endblock %}</title>
</head>
<body>
  <header>
    {% block header %}{% endblock %}
  </header>
  <main>
    {% block content %}{% endblock %}
  </main>
  <footer>
    {% block footer %}Default Footer{% endblock %}
  </footer>
</body>
</html>

Child Template (page.tpl)

{% extends "layout.tpl" %}

{% block title %}My Page Title{% endblock %}

{% block header %}
  <h1>Welcome to My Site</h1>
{% endblock %}

{% block content %}
  <p>This is the main content.</p>
{% endblock %}

Using super()

Access parent block content with {{ super() }}:

{% block footer %}
  {{ super() }}
  <p>Additional footer content</p>
{% endblock %}

Variables

Simple Variables

<p>Hello, {{ user.name }}!</p>

Nested Properties

Use dot notation to access nested properties:

<p>{{ user.address.city }}</p>

Auto-Escaping

All variables are automatically HTML-escaped for security:

$ctx = ['text' => '<script>alert("xss")</script>'];
{{ text }}  <!-- Outputs: &lt;script&gt;alert(&quot;xss&quot;)&lt;/script&gt; -->

URL Variables

URLs are URL-escaped for security:

<p>The site is at {{@ user.website }}!</p>

Raw Variables

Raw variables are not HTML-escaped for security:

<p>Good {{! timeofday }}!</p>

Never use untrusted (user-supplied) data in a raw template variable.


Control Structures

If Statements

{% if user.age >= 18 %}
  <p>Adult content</p>
{% elif user.age >= 13 %}
  <p>Teen content</p>
{% else %}
  <p>Child content</p>
{% endif %}

Supported operators: ==, !=, <, >, <=, >=, &&, ||, !

For Loops

<ul>
{% for item in items %}
  <li>{{ item }}</li>
{% endfor %}
</ul>

Loop Variables

Inside loops, you have access to special variables:

{% for product in products %}
  <p>Index: {{ product_key }}</p>
  <p>Name: {{ product.name }}</p>
{% endfor %}

The _key variable contains the array key or index.

Nested Loops

{% for category in categories %}
  <h2>{{ category.name }}</h2>
  <ul>
  {% for item in category.items %}
    <li>{{ item }}</li>
  {% endfor %}
  </ul>
{% endfor %}

Includes

Basic Include

{% include "partials/header.tpl" %}

Include with Parameters

Pass specific variables to included templates:

{% for item in items %}
  {% include "partials/item.tpl" with entry=item %}
{% endfor %}

In partials/item.tpl:

<li>{{ entry }}</li>

Multiple Parameters

{% include "partials/card.tpl" with title=product.name price=product.price %}

Escaping and Raw Output

Raw HTML Output

Use raw() or {{! var }} to output unescaped HTML:

$ctx = [
    'html_content' => star_raw_marker('<strong>Bold text</strong>')
];
{{ raw(html_content) }}  <!-- Outputs: <strong>Bold text</strong> -->

Important: Only use raw() with trusted content to prevent XSS attacks.

URL Escaping

Use esc_url() or {{@ var }} for URLs:

<a href="{{ esc_url(user.profile_url) }}">Profile</a>

Caching

How Caching Works

Star automatically compiles templates to pure PHP and caches them for performance. The cache is automatically invalidated when:

Cache Directory

Specify a cache directory when rendering:

echo star_render_template('page.tpl', $ctx, './templates', './cache');

The cache directory will be created automatically if it doesn't exist.

Cache Files

Cached files are stored as MD5 hashes of the template name:

cache/
  74a7dbf2831ed066620d84d1a43dd346.php
  a1b2c3d4e5f6g7h8i9j0k1l2m3n4o5p6.php

Clearing Cache

To clear the cache, simply delete the cache directory contents:

rm -rf cache/*

Or programmatically:

array_map('unlink', glob('./cache/*.php'));

Performance Benefits


API Reference

Core Functions

star_render_template($templatename, $ctx, $templatesbase, $cacheDir)

Renders a template with caching.

Parameters:

Returns: (string) Rendered HTML

Example:

$html = star_render_template('page.tpl', ['title' => 'Home'], './templates', './cache');

star_render_string_recursive($src, $ctx, $templatesbase, $currentdir)

Renders a template string without caching (for dynamic templates).

Parameters:

Returns: (string) Rendered HTML

Example:

$template = '<p>Hello, {{ name }}!</p>';
$html = star_render_string_recursive($template, ['name' => 'Alice'], './templates', getcwd());

Utility Functions

star_e($s)

HTML-escapes a string for safe output.

Parameters:

Returns: (string) Escaped string

Example:

echo star_e('<script>alert("xss")</script>');
// Outputs: &lt;script&gt;alert(&quot;xss&quot;)&lt;/script&gt;

star_esc_url($s)

URL-escapes a string.

Parameters:

Returns: (string) Escaped URL

Example:

$url = star_esc_url('http://example.com/?q=<test>');
// Returns: http://example.com/?q=&lt;test&gt;

star_raw_marker($s)

Marks a string as safe HTML (won't be escaped).

Parameters:

Returns: (array) Raw marker array

Example:

$ctx = [
    'safe_html' => star_raw_marker('<strong>Bold</strong>')
];

star_ctx_get($ctx, $path)

Gets a value from context using dot notation.

Parameters:

Returns: (mixed) Value or NULL if not found

Example:

$ctx = ['user' => ['name' => 'Alice']];
$name = star_ctx_get($ctx, 'user.name');  // Returns: 'Alice'

Best Practices

Security

  1. Never use raw() with user input - Always escape user-provided content
  2. Use esc_url() for URLs - Especially for user-provided URLs
  3. Validate context data - Ensure data passed to templates is sanitized

Performance

  1. Use caching in production - Always specify a cache directory
  2. Organize templates - Use subdirectories for better organization
  3. Minimize includes - Each include adds slight overhead during compilation

Template Organization

templates/
  layout.tpl           # Base layout
  page.tpl             # Page template
  partials/
    header.tpl         # Reusable header
    footer.tpl         # Reusable footer
    item.tpl           # List item component
  admin/
    dashboard.tpl      # Admin templates

Naming Conventions


Examples

Complete Example

PHP Code (index.php):

<?php
require 'star.php';

$ctx = [
    'page_title' => 'Product Catalog',
    'user' => [
        'name' => 'Alice',
        'is_admin' => true
    ],
    'products' => [
        ['name' => 'Laptop', 'price' => 999.99],
        ['name' => 'Mouse', 'price' => 24.99],
        ['name' => 'Keyboard', 'price' => 79.99]
    ]
];

echo star_render_template('catalog.tpl', $ctx, './templates', './cache');

Base Layout (templates/layout.tpl):

<!doctype html>
<html>
<head>
  <meta charset="utf-8">
  <title>{% block title %}My Store{% endblock %}</title>
</head>
<body>
  <header>
    <h1>My Store</h1>
    {% if user.is_admin %}
      <a href="/admin">Admin Panel</a>
    {% endif %}
  </header>
  <main>
    {% block content %}{% endblock %}
  </main>
  <footer>
    <p>&copy; 2025 My Store</p>
  </footer>
</body>
</html>

Catalog Template (templates/catalog.tpl):

{% extends "layout.tpl" %}

{% block title %}{{ page_title }} - My Store{% endblock %}

{% block content %}
  <h2>Welcome, {{ user.name }}!</h2>
  
  <div class="products">
    {% for product in products %}
      {% include "partials/product-card.tpl" with item=product %}
    {% endfor %}
  </div>
{% endblock %}

Product Card (templates/partials/product-card.tpl):

<div class="product-card">
  <h3>{{ item.name }}</h3>
  <p class="price">${{ item.price }}</p>
  <button>Add to Cart</button>
</div>

Troubleshooting

Template Not Found

Error: Template not found: templates/page.tpl

Solution: Check that:

Cache Directory Issues

Error: Cannot write to cache directory

Solution:

mkdir cache
chmod 755 cache

Syntax Errors

Error: Parse error in cached PHP

Solution:

  1. Delete cache directory contents
  2. Check template syntax
  3. Ensure all {% if %} have matching {% endif %}
  4. Ensure all {% for %} have matching {% endfor %}

Performance Issues

If templates render slowly:

  1. Ensure caching is enabled (pass $cacheDir parameter)
  2. Check cache directory is writable
  3. Verify cache files are being created in the cache directory

PHP Compatibility


License

Star is licensed GPL 2.0 or later.