Smarty Template Debugging¶
Advanced techniques for debugging Smarty templates in XOOPS themes and modules.
Diagnostic Flowchart¶
flowchart TD
A[Template Issue] --> B{Syntax Error?}
B -->|Yes| C[Check Braces]
B -->|No| D{Variable Issue?}
C --> C1[Match all braces]
C1 --> C2[Check tag format]
C2 --> C3[View error log]
D -->|Undefined| E[Check Assignment]
D -->|Wrong Value| F[Log Variable]
E --> E1[Verify PHP code]
E1 --> E2[Assign variable]
E2 --> E3[Clear cache]
F --> F1[Enable debug mode]
F1 --> F2[Dump variable]
F2 --> F3[Check logic]
C3 --> G{Issue Fixed?}
E3 --> G
F3 --> G
G -->|No| H[Enable Debug Console]
G -->|Yes| I[Problem Solved]
H --> J[Check compiled template]
J --> K[Review output]
K --> G Enable Smarty Debug Mode¶
Method 1: Admin Panel¶
XOOPS Admin > Settings > Performance: - Enable "Debug Output" - Set "Debug Level" to 2
Method 2: Code Configuration¶
<?php
// In mainfile.php or module code
require_once XOOPS_ROOT_PATH . '/class/smarty/Smarty.class.php';
$tpl = new XoopsTpl();
// Enable debug mode
$tpl->debugging = true;
// Optional: Set custom debug template
$tpl->debug_tpl = XOOPS_ROOT_PATH . '/class/smarty/debug.tpl';
// Render template
$tpl->display('file:template.html');
?>
Method 3: Debug Popup in Browser¶
This shows a popup with all assigned variables.
Common Smarty Debug Techniques¶
Dump All Variables¶
<?php
// In PHP code
$tpl = new XoopsTpl();
// Get all assigned variables
$variables = $tpl->get_template_vars();
echo "<pre>";
print_r($variables);
echo "</pre>";
?>
In template:
{* Display debug info *}
<div style="border: 1px red solid; background: #ffffcc; padding: 10px;">
<h3>Debug Info</h3>
{debug}
</div>
Log Specific Variable¶
<?php
$tpl = new XoopsTpl();
// Check if variable exists
$user = $tpl->get_template_var('user');
if ($user === null) {
error_log("Variable 'user' not assigned to template");
} else {
error_log("User data: " . json_encode($user));
}
?>
Check Variable in Template¶
{* Dump variable for debugging *}
<pre>
{$variable|print_r}
</pre>
{* Or with label *}
<pre>
User Data:
{$user|print_r}
</pre>
{* Check if variable exists *}
{if isset($user)}
<p>User: {$user.name}</p>
{else}
<p style="color: red;">ERROR: user variable not set</p>
{/if}
View Compiled Templates¶
Smarty compiles templates to PHP for performance. Debug by viewing compiled code:
# Find compiled templates
ls -la xoops_data/caches/smarty_compile/
# View compiled template
cat xoops_data/caches/smarty_compile/filename.php
<?php
// Create debug script to view latest compiled template
$compile_dir = XOOPS_CACHE_PATH . '/smarty_compile';
// Get latest compiled file
$files = glob($compile_dir . '/*.php');
usort($files, function($a, $b) {
return filemtime($b) - filemtime($a);
});
if ($files) {
echo "<h1>Latest Compiled Template</h1>";
echo "<pre>";
echo htmlspecialchars(file_get_contents($files[0]));
echo "</pre>";
}
?>
Analyze Template Compilation¶
<?php
// Create modules/yourmodule/debug_smarty.php
require_once '../../mainfile.php';
require_once XOOPS_ROOT_PATH . '/vendor/autoload.php';
$tpl = new XoopsTpl();
$ray = ray(); // If using Ray debugger
$ray->group('Smarty Configuration');
// Get Smarty paths
$ray->label('Compile Dir')->info($tpl->getCompileDir());
$ray->label('Cache Dir')->info($tpl->getCacheDir());
$ray->label('Template Dirs')->dump($tpl->getTemplateDir());
// Check compiled templates
$compile_dir = $tpl->getCompileDir();
$compiled_files = glob($compile_dir . '*.php');
$ray->label('Compiled Templates')->info(count($compiled_files) . " files");
// Show compilation stats
$total_size = 0;
foreach ($compiled_files as $file) {
$total_size += filesize($file);
}
$ray->label('Compiled Cache Size')->info(round($total_size / 1024 / 1024, 2) . " MB");
// Check cache directory
$cache_dir = $tpl->getCacheDir();
$cache_files = glob($cache_dir . '*.php');
$ray->label('Cached Templates')->info(count($cache_files) . " files");
$ray->groupEnd();
?>
Debug Specific Issues¶
Issue 1: Variable Shows as Empty¶
<?php
$tpl = new XoopsTpl();
// Check what's assigned
$user = $tpl->get_template_var('user');
if ($user === null) {
error_log("ERROR: 'user' not assigned");
} elseif (empty($user)) {
error_log("WARNING: 'user' is empty");
} else {
error_log("user data: " . json_encode($user));
}
// Also check in template
?>
Template debug:
{if !isset($user)}
<span style="color: red;">ERROR: user variable not set</span>
{elseif empty($user)}
<span style="color: orange;">WARNING: user is empty</span>
{else}
<p>User: {$user.name}</p>
{/if}
Issue 2: Array Key Not Found¶
{* Use safe array access *}
{* WRONG - causes undefined index notice *}
{$array.key}
{* CORRECT - check first *}
{if isset($array.key)}
{$array.key}
{else}
<span style="color: red;">Key 'key' not found in array</span>
{/if}
{* Or use default *}
{$array.key|default:'key not found'}
Debug in PHP:
<?php
$array = $tpl->get_template_var('array');
if (!isset($array['key'])) {
error_log("Missing key in array: " . json_encode(array_keys($array)));
}
?>
Issue 3: Plugin/Modifier Not Found¶
<?php
// Create custom modifier: plugins/modifier.debug.php
function smarty_modifier_debug($var) {
return '<pre style="background: #ffffcc; border: 1px solid red;">' .
htmlspecialchars(json_encode($var, JSON_PRETTY_PRINT)) .
'</pre>';
}
?>
Register in code:
<?php
$tpl = new XoopsTpl();
$tpl->addPluginDir(XOOPS_ROOT_PATH . '/modules/yourmodule/plugins');
$tpl->register_modifier('debug', 'smarty_modifier_debug');
?>
Use in template:
Issue 4: Nested Array Display¶
{* Debug nested arrays *}
<div style="background: #f5f5f5; padding: 10px; border: 1px solid #ccc;">
<h3>Data Debug</h3>
<pre>{$data|@json_encode}</pre>
</div>
{* Or iterate and show *}
<h3>User Data:</h3>
{foreach $user as $key => $value}
<p><strong>{$key}:</strong> {$value|escape}</p>
{/foreach}
{* Check for specific keys *}
<h3>Verification:</h3>
<ul>
<li>Has 'name': {if isset($user.name)}✓{else}✗{/if}</li>
<li>Has 'email': {if isset($user.email)}✓{else}✗{/if}</li>
<li>Has 'id': {if isset($user.id)}✓{else}✗{/if}</li>
</ul>
Create Debug Template¶
{* Create themes/mytheme/debug.html *}
{strip}
<div style="background: #fff3cd; border: 2px solid #ff0000; padding: 20px; margin: 20px 0;">
<h2 style="color: #ff0000;">🔍 SMARTY DEBUG MODE</h2>
<h3>Assigned Variables:</h3>
<div style="background: white; padding: 10px; border: 1px solid #999; overflow-x: auto; max-height: 400px;">
{* Show all variables *}
{debug output='html'}
</div>
<h3>Template Information:</h3>
<table style="width: 100%; border-collapse: collapse;">
<tr>
<td style="border: 1px solid #999; padding: 5px;"><strong>Current Template:</strong></td>
<td style="border: 1px solid #999; padding: 5px;">{$smarty.template}</td>
</tr>
<tr>
<td style="border: 1px solid #999; padding: 5px;"><strong>Smarty Version:</strong></td>
<td style="border: 1px solid #999; padding: 5px;">{$smarty.version}</td>
</tr>
<tr>
<td style="border: 1px solid #999; padding: 5px;"><strong>Current Time:</strong></td>
<td style="border: 1px solid #999; padding: 5px;">{$smarty.now|date_format:"%Y-%m-%d %H:%M:%S"}</td>
</tr>
</table>
<p style="color: #ff0000;"><strong>⚠️ Remove this debug code before going to production!</strong></p>
</div>
{/strip}
Performance Debugging¶
Measure Template Rendering¶
<?php
$start = microtime(true);
$tpl->display('file:template.html');
$render_time = (microtime(true) - $start) * 1000;
error_log("Template rendered in: {$render_time}ms");
if ($render_time > 100) {
error_log("WARNING: Slow template rendering");
}
?>
Check Cache Effectiveness¶
<?php
$compile_dir = XOOPS_CACHE_PATH . '/smarty_compile';
$cache_dir = XOOPS_CACHE_PATH . '/smarty_cache';
// Count files
$compiled = count(glob($compile_dir . '*.php'));
$cached = count(glob($cache_dir . '*.php'));
// Size
$compile_size = 0;
foreach (glob($compile_dir . '*') as $file) {
$compile_size += filesize($file);
}
$cache_size = 0;
foreach (glob($cache_dir . '*') as $file) {
$cache_size += filesize($file);
}
echo "Compiled: $compiled files (" . round($compile_size/1024/1024, 2) . "MB)";
echo "Cached: $cached files (" . round($cache_size/1024/1024, 2) . "MB)";
// Age of files
$oldest_compile = min(array_map('filemtime', glob($compile_dir . '*')));
$oldest_cache = min(array_map('filemtime', glob($cache_dir . '*')));
echo "Oldest compiled: " . date('Y-m-d H:i:s', $oldest_compile);
echo "Oldest cached: " . date('Y-m-d H:i:s', $oldest_cache);
?>
Clear and Rebuild Cache¶
<?php
// Force rebuild of all templates
$tpl = new XoopsTpl();
// Clear cache
$tpl->clearCache();
$tpl->clearCompiledTemplate();
// Force recompilation
$tpl->force_compile = true;
// Render all module templates
$modules = ['mymodule', 'publisher', 'downloads'];
foreach ($modules as $module) {
$template = "file:" . XOOPS_ROOT_PATH . "/modules/$module/templates/index.html";
try {
$tpl->display($template);
error_log("Compiled: $module");
} catch (Exception $e) {
error_log("Error compiling $module: " . $e->getMessage());
}
}
// Disable force compile after done
$tpl->force_compile = false;
?>
Debugging Workflow¶
Step-by-Step Debug Process¶
graph TD
A[Template Not Working] --> B["Step 1: Check Syntax"]
B --> C["Step 2: Enable Debug"]
C --> D["Step 3: Check Variables"]
D --> E["Step 4: View Compiled"]
E --> F["Step 5: Verify Output"]
B --> B1["✓ Match braces"]
C --> C1["✓ Enable debug mode"]
D --> D1["✓ Dump variables"]
E --> E1["✓ Review PHP code"]
F --> F1["✓ Check HTML output"] Debug Helper Functions¶
<?php
// Create class/TemplateDebugger.php
class TemplateDebugger {
private static $tpl = null;
private static $debug_info = [];
public static function init(&$smarty) {
self::$tpl = $smarty;
}
public static function dumpVar($name) {
$var = self::$tpl->get_template_var($name);
if ($var === null) {
self::$debug_info[] = "Variable '$name' not found";
return;
}
self::$debug_info[] = "$name: " . json_encode($var);
}
public static function checkVar($name, $keys = []) {
$var = self::$tpl->get_template_var($name);
if ($var === null) {
return "ERROR: Variable '$name' not assigned";
}
if (!is_array($var)) {
return "$name is not an array";
}
$missing = [];
foreach ($keys as $key) {
if (!isset($var[$key])) {
$missing[] = $key;
}
}
if ($missing) {
return "Missing keys in '$name': " . implode(', ', $missing);
}
return "OK: Variable '$name' has all required keys";
}
public static function getReport() {
return implode("\n", self::$debug_info);
}
public static function logAll() {
$vars = self::$tpl->get_template_vars();
error_log("Template Variables: " . json_encode($vars));
}
}
?>
Usage:
<?php
TemplateDebugger::init($tpl);
TemplateDebugger::dumpVar('user');
TemplateDebugger::checkVar('articles', ['id', 'title', 'author']);
error_log(TemplateDebugger::getReport());
?>