Yes that’s another template engine in PHP. I’ve been using Smarty for years. It’s easy to install and easy to use. But there is something I don’t like in Smarty. I need to learn another language (smarty markup) to create my templates. Normally my templates are not very complex. I only use them to move HTML code outside PHP. Basically my templates are: HTML and some variables that pass from PHP to tpl. Sometimes I need to do a loop. I know Smarty has a lot of helpers but I never use them.
Now I’m in a project and I must to choose a template engine. This project don’t have any dependencies to any other libraries, so I don’t want to include full Smarty library to my simple templates. A quick search in Google gives us a list of template engines in PHP. Mostly all engines use PHP as template language. That’s a good decision. In fact PHP is a template language so, why we need to use another one?. I think the main problem of using PHP as template language is the temptation of put logic in the template and have a nice spaghetti code.
So I am going to build a simple template engine. Let’s start:
As always I like to start from the interface. When I start a library I like to think the library is finished (before start coding. cool isn’t it?) and write the code to use it. Finally when the I like the interface I start coding the library.
I want this template:
<h1>Example of tpl</h1> var1 = _('var1') ?> var2 = _('var2') ?> foreach ($this->_('var3') as $item) { echo $this->clean($item); } ?>
And I want to call it with something like this:
echo Tpl::singleton()->init('demo1.phtml')->render(array( 'var1' => 1, 'var2' => 2, 'var3' => array(1, 2, 3, 4, 5, 6, 7) ));
Basically Tpl class will be a container to collect the configuration and init function will be a factory of another class (Tpl_Instance) that will do the templating itself.
render function is the main function. Basically call to php’s include function with the selected tpl.
if (!is_file($_tplFile)) { throw new Exception('Template file not found'); } ini_set('implicit_flush',false); ob_start(); include ($_tplFile); $out = ob_get_contents(); ob_end_clean(); ini_set('implicit_flush',true); return $out;
As we see the tpl file is a simple PHP file included in our script with Tpl_Instance::render. So $this in our tpl’s PHP code is the instance of Tpl_Instance. That means whe can use protected and even private functions of Tpl_Instance.
Now I going to show different usages of the library:
// Sets the path of templates. If nuls asumes file is absolute Tpl::singleton()->setConf(Tpl::TPL_DIR, realpath(dirname(__FILE__))); echo Tpl::singleton()->init('demo1.phtml')->render(array( 'var1' => 1, 'var2' => 2, 'var3' => array(1, 2, 3, 4, 5, 6, 7) ));
// The same instance a different template and params added in a different way $tpl = Tpl::singleton()->init('demo2.phtml'); $tpl->addParam('header', 'header'); $tpl->addParam('footer', 'footer'); echo $tpl->render();
// Disable exceptions if we don't assign a variable Tpl::singleton()->setConf(Tpl::THROW_EXCEPTION_WITH_PARAMS, false); $tpl = Tpl::singleton()->init('demo1.phtml'); $tpl->addParam('var1', 'aaaa'); $tpl->addParam('var3', array(1, 2, 3, 4, 5, 6, 7)); echo $tpl->render();
// Using factory $objTpl = Tpl::factory(); $objTpl->setConf(Tpl::THROW_EXCEPTION_WITH_PARAMS, true); try { $tpl = $objTpl->init('demo1.phtml'); $tpl->addParam('var1', 'aaaa'); $tpl->addParam('var3', array(1, 2, 3, 4, 5, 6, 7)); echo $tpl->render(); } catch (Exception $e) { echo "" . $e->getMessage() . " "; }
And like always full source code is available on google code.
I think if temptation of putting logic in the template is the only motivator to use a template engine. Your template engine is not going to prevent it because the template is a php file.
I think your template engine can be reduced to one function
function render((string) $template,(array) $vars)
{
extract($vars);
ob_start();
include($template);
return ob_get_clean();
}
If you want to create a minimal template engine don’t add fat.
Totally agree. The temptation of building logic in the template is the bad side of using php as template language. But I preffer this risk than building a new language.
In the other side, basically the template engine is almost like you say. I use two classes because I want to use the interface I show you in the examples. I know I can reduce the code to the example you show and I can reduce the library to one class instead of two but the main objetive for me if the interface