I'm required to create a simple template engine; I can't use Twig or Smarty, etc. because the designer on the project needs to be able to just copy/paste her HTML into the template with no configuration, muss/fuss, whatever. It's gotta be really easy.
So I created something that will allow her to do just that, by placing her content between {{ CONTENT }}
{{ !CONTENT }}
tags.
My only problem is that I want to make sure that if she uses multiple spaces in the tags - or NO spaces - it won't break; i.e. {{ CONTENT }}
or {{CONTENT}}
What I have below accomplishes this, but I'm afraid it may be overkill. Anybody know a way to simplify this function?
function defineContent($tag, $string) {
$offset = strlen($tag) + 6;
// add a space to our tags if none exist
$string = str_replace('{{'.$tag, '{{ '.$tag, $string);
$string = str_replace($tag.'}}', $tag.' }}', $string);
// strip consecutive spaces
$string = preg_replace('/\s+/', ' ', $string);
// now that extra spaces have been stripped, we're left with this
// {{ CONTENT }} My content goes here {{ !CONTENT }}
// remove the template tags
$return = substr($string, strpos($string, '{{ '.$tag.' }}') + $offset);
$return = substr($return, 0, strpos($return, '{{ !'.$tag.' }}'));
return $return;
}
// here's the string
$string = '{{ CONTENT }} My content goes here {{ !CONTENT }}';
// run it through the function
$content = defineContent('CONTENT', $string);
echo $content;
// gives us this...
My content goes here
Ended up creating a repo, for anyone interested.
https://github.com/timgavin/tinyTemplate
I would suggest to take a look at variable extraction into the template scope. It's a bit easier to maintain and less overhead, than the replace approach and its often easier to use for the designer. In its basic form, its just PHP variables and short tags.
It depends on which side you generate, e.g. a table and its rows (or complete content blocks) - it could be just <?=$table?>
;) Less work for the designer, more work for you. Or just provide a few rendering examples and helpers, because copy/pasting examples should always work, even with an untrained designer.
Template
The template is just HTML mixed with <?=$variable?>
- uncluttered.
src/Templates/Article.php
<html>
<body>
<h1><?=$title?></h1>
<div><?=$content?></div>
</body>
</html>
Usage
src/Controller/Article.php
...
// initalize
$view = new View;
// assign
$view->data['title'] = 'The title';
$view->data['content'] = 'The body';
// render
$view->render(dirname(__DIR__) . '/Templates/Article.php');
View / TemplateRenderer
The core function here is render()
. The template file is included and the variable extraction happens in a closure to avoid any variable clashes/scope problems.
src/View.php
class View
{
/**
* Set data from controller: $view->data['variable'] = 'value';
* @var array
*/
public $data = [];
/**
* @var sting Path to template file.
*/
function render($template)
{
if (!is_file($template)) {
throw new \RuntimeException('Template not found: ' . $template);
}
// define a closure with a scope for the variable extraction
$result = function($file, array $data = array()) {
ob_start();
extract($data, EXTR_SKIP);
try {
include $file;
} catch (\Exception $e) {
ob_end_clean();
throw $e;
}
return ob_get_clean();
};
// call the closure
echo $result($template, $this->data);
}
}
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With