Skip to content

Instantly share code, notes, and snippets.

@rohjay
Last active December 16, 2020 22:09
Show Gist options
  • Save rohjay/a8be087e3f190cebccb6eaaf0f0a6e0f to your computer and use it in GitHub Desktop.
Save rohjay/a8be087e3f190cebccb6eaaf0f0a6e0f to your computer and use it in GitHub Desktop.
<?php
/**
This is a simple class to help you render values into templates, rather than echoing large strings of html/whatever.
Usage:
// Set the base directory of all of your template files and instantiate the Templater
$base_dir = __DIR__ . '/templates';
$templater = new Templater($base_dir);
// A simple example [template path: __DIR__ . '/templates/index.php']:
$templater->view('index.php');
// A more usable example [template path: __DIR__ . '/templates/account/dashboard.php']:
$account = ['name'=>'Ryan', 'birthday'=>'02/26/1983'];
$templater->view('account/dashboard.php', $account);
// Now your template might look something like this [file path: __DIR__ . '/templates/account/dashboard.php']:
<h1>Hello, <?php $this->e($data['name']) ?>!</h1>
<p>Your birthday is on <?php $this->e($data['birthday']) ?> =D</p>
// Inside your templates, you can also render additional templates using `$this->view()`
// For instance, if inside my previous template file, I also included a sidebar, it might look like this:
<h1>Hello, <?php $this->e($data['name']) ?>!</h1>
<p>Your birthday is on <?php $this->e($data['birthday']) ?> =D</p>
<?php $this->view('sidebar.php') ?>
*/
class Templater
{
public $template_base_dir;
// Must be constructed with a valid base dir for your templates... add validation to taste =P
public function __construct($template_base_dir)
{
$this->template_base_dir = rtrim($template_base_dir, DIRECTORY_SEPARATOR) . DIRECTORY_SEPARATOR;
}
// Verify that the template being requested is within the correct folder and exists
public function is_valid($template_path)
{
$realpath = realpath($template_path);
// If it's a real path (ie: if `realpath` didn't return false)
return $realpath
// starts with our template directory (which `realpath` susses out all the ../../ stuff)
&& strpos($realpath, $template_path) === 0
// and the file is readable... let's assume it's valid
&& is_readable($template_path);
}
// Output the rendered template
public function view($template_file, $data=array())
{
$template_path = $this->template_base_dir . ltrim($template_file,'/');
if ( !$this->is_valid($template_path) ) {
throw new \Exception("Invalid Template File Requested: " . $template_path, 403); // Forbidden
}
require_once $template_path;
}
// Return the rendered output as a string
public function grab($template_file, $data=array())
{
ob_start();
$this->view($template_file, $data);
$results = ob_get_contents();
ob_end_clean();
return $results;
}
// To escape and echo html safe values easily...
public function e($value, $return=false)
{
if ( $return ) {
return htmlspecialchars($value);
}
echo htmlspecialchars($value);
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment