CommentTemplate
CommentTemplate is a powerful PHP template engine with asset compilation, template inheritance, and variable processing. It provides a simple yet flexible way to manage templates with built-in CSS/JS minification and caching.
Features
- Template Inheritance: Use layouts and include other templates
- Asset Compilation: Automatic CSS/JS minification and caching
- Variable Processing: Template variables with filters and commands
- Base64 Encoding: Inline assets as data URIs
- Flight Framework Integration: Optional integration with Flight PHP framework
Installation
Install with composer.
composer require knifelemon/comment-templateBasic Configuration
There are some basic configuration options to get started. You can read more about them in the CommentTemplate Repo.
Method 1: Using Callback Function
<?php
require_once 'vendor/autoload.php';
use KnifeLemon\CommentTemplate\Engine;
$app = Flight::app();
$app->register('view', Engine::class, [], function (Engine $engine) use ($app) {
// Root directory (where index.php is) - the document root of your web application
$engine->setPublicPath(__DIR__);
// Template files directory - supports both relative and absolute paths
$engine->setSkinPath('views'); // Relative to public path
// Where compiled assets will be stored - supports both relative and absolute paths
$engine->setAssetPath('assets'); // Relative to public path
// Template file extension
$engine->setFileExtension('.php');
});
$app->map('render', function(string $template, array $data) use ($app): void {
echo $app->view()->render($template, $data);
});Method 2: Using Constructor Parameters
<?php
require_once 'vendor/autoload.php';
use KnifeLemon\CommentTemplate\Engine;
$app = Flight::app();
// __construct(string $publicPath = "", string $skinPath = "", string $assetPath = "", string $fileExtension = "")
$app->register('view', Engine::class, [
__DIR__, // publicPath - root directory (where index.php is)
'views', // skinPath - templates path (supports relative/absolute)
'assets', // assetPath - compiled assets path (supports relative/absolute)
'.php' // fileExtension - template file extension
]);
$app->map('render', function(string $template, array $data) use ($app): void {
echo $app->view()->render($template, $data);
});Path Configuration
CommentTemplate provides intelligent path handling for both relative and absolute paths:
Public Path
The Public Path is the root directory of your web application, typically where index.php resides. This is the document root that web servers serve files from.
// Example: if your index.php is at /var/www/html/myapp/index.php
$template->setPublicPath('/var/www/html/myapp'); // Root directory
// Windows example: if your index.php is at C:\xampp\htdocs\myapp\index.php
$template->setPublicPath('C:\\xampp\\htdocs\\myapp');Templates Path Configuration
Templates path supports both relative and absolute paths:
$template = new Engine();
$template->setPublicPath('/var/www/html/myapp'); // Root directory (where index.php is)
// Relative paths - automatically combined with public path
$template->setSkinPath('views'); // → /var/www/html/myapp/views/
$template->setSkinPath('templates/pages'); // → /var/www/html/myapp/templates/pages/
// Absolute paths - used as-is (Unix/Linux)
$template->setSkinPath('/var/www/templates'); // → /var/www/templates/
$template->setSkinPath('/full/path/to/templates'); // → /full/path/to/templates/
// Windows absolute paths
$template->setSkinPath('C:\\www\\templates'); // → C:\www\templates\
$template->setSkinPath('D:/projects/templates'); // → D:/projects/templates/
// UNC paths (Windows network shares)
$template->setSkinPath('\\\\server\\share\\templates'); // → \\server\share\templates\Asset Path Configuration
Asset path also supports both relative and absolute paths:
// Relative paths - automatically combined with public path
$template->setAssetPath('assets'); // → /var/www/html/myapp/assets/
$template->setAssetPath('static/files'); // → /var/www/html/myapp/static/files/
// Absolute paths - used as-is (Unix/Linux)
$template->setAssetPath('/var/www/cdn'); // → /var/www/cdn/
$template->setAssetPath('/full/path/to/assets'); // → /full/path/to/assets/
// Windows absolute paths
$template->setAssetPath('C:\\www\\static'); // → C:\www\static\
$template->setAssetPath('D:/projects/assets'); // → D:/projects/assets/
// UNC paths (Windows network shares)
$template->setAssetPath('\\\\server\\share\\assets'); // → \\server\share\assets\Smart Path Detection:
- Relative Paths: No leading separators (
/,\) or drive letters - Unix Absolute: Starts with
/(e.g.,/var/www/assets) - Windows Absolute: Starts with drive letter (e.g.,
C:\www,D:/assets) - UNC Paths: Starts with
\\(e.g.,\\server\share)
How it works:
- All paths are automatically resolved based on type (relative vs absolute)
- Relative paths are combined with the public path
@cssand@jscreate minified files in:{resolvedAssetPath}/css/or{resolvedAssetPath}/js/@assetcopies single files to:{resolvedAssetPath}/{relativePath}@assetDircopies directories to:{resolvedAssetPath}/{relativePath}- Smart caching: files only copied when source is newer than destination
Template Directives
Layout Inheritance
Use layouts to create a common structure:
layout/global_layout.php:
<!DOCTYPE html>
<html>
<head>
<title>{$title}</title>
</head>
<body>
<!--@contents-->
</body>
</html>view/page.php:
<!--@layout(layout/global_layout)-->
<h1>{$title}</h1>
<p>{$content}</p>Asset Management
CSS Files
<!--@css(/css/styles.css)--> <!-- Minified and cached -->
<!--@cssSingle(/css/critical.css)--> <!-- Single file, not minified -->JavaScript Files
CommentTemplate supports different JavaScript loading strategies:
<!--@js(/js/script.js)--> <!-- Minified, loaded at bottom -->
<!--@jsAsync(/js/analytics.js)--> <!-- Minified, loaded at bottom with async -->
<!--@jsDefer(/js/utils.js)--> <!-- Minified, loaded at bottom with defer -->
<!--@jsTop(/js/critical.js)--> <!-- Minified, loaded in head -->
<!--@jsTopAsync(/js/tracking.js)--> <!-- Minified, loaded in head with async -->
<!--@jsTopDefer(/js/polyfill.js)--> <!-- Minified, loaded in head with defer -->
<!--@jsSingle(/js/widget.js)--> <!-- Single file, not minified -->
<!--@jsSingleAsync(/js/ads.js)--> <!-- Single file, not minified, async -->
<!--@jsSingleDefer(/js/social.js)--> <!-- Single file, not minified, defer -->Asset Directives in CSS/JS Files
CommentTemplate also processes asset directives within CSS and JavaScript files during compilation:
CSS Example:
/* In your CSS files */
@font-face {
font-family: 'CustomFont';
src: url('<!--@asset(fonts/custom.woff2)-->') format('woff2');
}
.background-image {
background: url('<!--@asset(images/bg.jpg)-->');
}
.inline-icon {
background: url('<!--@base64(icons/star.svg)-->');
}JavaScript Example:
/* In your JS files */
const fontUrl = '<!--@asset(fonts/custom.woff2)-->';
const imageData = '<!--@base64(images/icon.png)-->';Base64 Encoding
<!--@base64(images/logo.png)--> <!-- Inline as data URI -->Example:
<!-- Inline small images as data URIs for faster loading -->
<img src="<!--@base64(images/logo.png)-->" alt="Logo">
<div style="background-image: url('<!--@base64(icons/star.svg)-->');">
Small icon as background
</div>Asset Copying
<!--@asset(images/photo.jpg)--> <!-- Copy single asset to public directory -->
<!--@assetDir(assets)--> <!-- Copy entire directory to public directory -->Example:
<!-- Copy and reference static assets -->
<img src="<!--@asset(images/hero-banner.jpg)-->" alt="Hero Banner">
<a href="<!--@asset(documents/brochure.pdf)-->" download>Download Brochure</a>
<!-- Copy entire directory (fonts, icons, etc.) -->
<!--@assetDir(assets/fonts)-->
<!--@assetDir(assets/icons)-->Template Includes
<!--@import(components/header)--> <!-- Include other templates -->Example:
<!-- Include reusable components -->
<!--@import(components/header)-->
<main>
<h1>Welcome to our website</h1>
<!--@import(components/sidebar)-->
<div class="content">
<p>Main content here...</p>
</div>
</main>
<!--@import(components/footer)-->Variable Processing
Basic Variables
<h1>{$title}</h1>
<p>{$description}</p>Variable Filters
{$title|upper} <!-- Convert to uppercase -->
{$content|lower} <!-- Convert to lowercase -->
{$html|striptag} <!-- Strip HTML tags -->
{$text|escape} <!-- Escape HTML -->
{$multiline|nl2br} <!-- Convert newlines to <br> -->
{$html|br2nl} <!-- Convert <br> tags to newlines -->
{$description|trim} <!-- Trim whitespace -->
{$subject|title} <!-- Convert to title case -->Variable Commands
{$title|default=Default Title} <!-- Set default value -->
{$name|concat= (Admin)} <!-- Concatenate text -->Variable Commands
{$content|striptag|trim|escape} <!-- Chain multiple filters -->Comments
Template comments are completely removed from the output and won't appear in the final HTML:
{* This is a single-line template comment *}
{*
This is a multi-line
template comment
that spans several lines
*}
<h1>{$title}</h1>
{* Debug comment: checking if title variable works *}
<p>{$content}</p>Note: Template comments {* ... *} are different from HTML comments <!-- ... -->. Template comments are removed during processing and never reach the browser.
Example Project Structure
project/
├── source/
│ ├── layouts/
│ │ └── default.php
│ ├── components/
│ │ ├── header.php
│ │ └── footer.php
│ ├── css/
│ │ ├── bootstrap.min.css
│ │ └── custom.css
│ ├── js/
│ │ ├── app.js
│ │ └── bootstrap.min.js
│ └── homepage.php
├── public/
│ └── assets/ # Generated assets
│ ├── css/
│ └── js/
└── vendor/