STAR(7) Linux User Manuals STAR(7)

star - lightweight, fast PHP template engine

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

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.

Simply include the star.php file in your project:

<?php
require 'star.php';

<?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)
'./cache' // Cache directory (optional) );

Templates use standard HTML comments:

<!-- This is a comment -->

And also Star comments:

{# This is a comment #}

Use hyphens to trim whitespace around template tags:

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

<!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>

{% 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 %}

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

{% block footer %}

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

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

Use dot notation to access nested properties:

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

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; -->

URLs are URL-escaped for security:

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

Raw variables are not HTML-escaped for security:

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

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

{% if user.age >= 18 %}

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

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

Odd/Even rows for numeric keys:

{% if product_key % 2 %}ODD{% else %}EVEN{% endif %}

Zero is treated as even for this purpose, because 0 % 2 returns 0. Odd numbers return 1.

<ul>
{% for item in items %}

<li>{{ item }}</li> {% endfor %} </ul>

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.

{% for category in categories %}

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

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

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>

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

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.

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

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

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

•Any template file is modified
•Any parent template (via extends) is modified
•Any included template is modified

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.

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

cache/

74a7dbf2831ed066620d84d1a43dd346.php
a1b2c3d4e5f6g7h8i9j0k1l2m3n4o5p6.php

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

rm -rf cache/*

Or programmatically:

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

•First render: Template is compiled and cached (slower)
•Subsequent renders: Cached PHP is executed directly (very fast)
•No regex processing after compilation
•Includes are pre-resolved at compile time

star_render_template(templatename, ctx, templatesbase, cacheDir)

Renders a template with caching.

Parameters:

•templatename (string): Template file relative to templates directory
•ctx (array): Context data to pass to the template
•templatesbase (string, optional): Absolute path to templates directory, default DIR__.'/templates'
•cacheDir (string, optional): Path to cache directory, default DIR__.'/cache'

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:

•src (string): Template source code
•ctx (array): Context data
•templatesbase (string): Absolute path to templates directory
•currentdir (string): Current working directory

Returns: (string) Rendered HTML

Example:

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

star_e(s)

HTML-escapes a string for safe output.

Parameters:

•s (string): String to escape

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:

•s (string): URL to escape

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:

•s (string): HTML content

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:

•ctx (array): Context array
•path (string): Dot-separated path (e.g., 'user.name')

Returns: (mixed) Value or NULL if not found

Example:

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

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

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

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

•Use .tpl extension for template files
•Use lowercase with hyphens: user-profile.tpl
•Use descriptive names: product-card.tpl not card.tpl

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>

Error: Template not found: templates/page.tpl

Solution: Check that:

•The template file exists
•The path is correct relative to the templates directory
•File permissions allow reading

Error: Cannot write to cache directory

Solution:

mkdir cache
chmod 755 cache

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 %}

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

•Minimum PHP Version: 7.3
•Tested with: PHP 7.3, 7.4, 8.0, 8.1, 8.2

Maintained by Ron Guerin <ron@vnetworx.net>.

Star is licensed GPL 2.0 or later.

2025-11-18 November 2025