| 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: <script>alert("xss")</script> -->
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:
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'));
star_render_template(templatename, ctx, templatesbase, cacheDir)
Parameters:
Returns: (string) Rendered HTML
Example:
$html = star_render_template('page.tpl', ['title' => 'Home'], './templates', './cache');
star_render_string_recursive(src, ctx, templatesbase, currentdir)
Parameters:
Returns: (string) Rendered HTML
Example:
$template = '<p>Hello, {{ name }}!</p>';
$html = star_render_string_recursive($template, ['name' => 'Alice'], './templates', getcwd());
star_e(s)
Parameters:
Returns: (string) Escaped string
Example:
echo star_e('<script>alert("xss")</script>');
// Outputs: <script>alert("xss")</script>
star_esc_url(s)
Parameters:
Returns: (string) Escaped URL
Example:
$url = star_esc_url('http://example.com/?q=<test>');
// Returns: http://example.com/?q=<test>
star_raw_marker(s)
Parameters:
Returns: (array) Raw marker array
Example:
$ctx = [
'safe_html' => star_raw_marker('<strong>Bold</strong>') ];
star_ctx_get(ctx, path)
Parameters:
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
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>© 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:
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
Maintained by Ron Guerin <ron@vnetworx.net>.
Star is licensed GPL 2.0 or later.
| 2025-11-18 | November 2025 |