Wednesday, June 20, 2012

Replace Smarty with PHP templates

In many performance guides, Smarty is considered to be removed to speed up things. But oftentimes it's not Smarty causing performance problems, but rather big modifier chains not being cached. To point this out, we need to profile our template which is quite difficult when Smarty compiles in into something unreadable. So we need a quick and easy way to replace the Smarty template engine with pure PHP code. Since Smarty can't do more than PHP, let's replace Smarty with simple PHP templates.

So I'm providing here a small guide to replace Smarty with simple PHP based templates. These can be also cached by APC without any compiler.

First thing: Smarty configuration files
e.g. core.conf
foo = bar

[core] 
logo = public/img/logo.png 
link = http://www.simple-groupware.de 
notice = Photo from xy 
bg_grey = #F5F5F5

Now let's convert it to PHP:
core_conf.php
<?php
  $config = array(
    "logo" => "public/img/logo.png",
    "bg_grey" => "#F5F5F5" 
  ); 
  $config["core"] = array( 
    "logo" => "public/img/logocore.png", 
    "link" => "http://www.simple-groupware.de", 
    "notice" => "Photo from xy"
  );

Next thing: Smarty templates
main.tpl
{config_load file="core.conf" section="core"}
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd"> 
<html xmlns="http://www.w3.org/1999/xhtml"> 
<head> 
  <title>{$smarty.const.TITLE|escape:"html"}: 
    {$page.title|default:$page.name|escape:"html"}</title> 
  <meta name="description" content="{$description|escape:"html"}" /> 
  <meta http-equiv="expires" content="{"r"|date}">  
</head> 
<body>
  <img src="{#logo#}" />
  <ul style="background-color: {#bg_grey#};">  
  {foreach from=$list key=key item=item} 
    <li>{$key}: {$item|escape:"html"}</li> 
  {/foreach} 
  </ul>  
</body> 
</html> 

Conversion to PHP:
main_tpl.php
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd"> 
<html xmlns="http://www.w3.org/1999/xhtml"> 
<head> 
  <title><?= q(TITLE) ?>: 
    <?= q($this->page['title'] ?: $this->page['name']) ?></title> 
  <meta name="description" content="<?= q($this->description) ?>" /> 
  <meta http-equiv="expires" content="<?= date('r') ?>"> 
</head> 
<body> 
  <img src="<?= $this->c('core', 'logo') ?>" />
  <ul style="background-color: <?= $this->c('bg_grey') ?>"> 
  <? foreach ($this->list as $key=>$item) { ?> 
    <li><?= $key ?>: <?= q($item) ?></li> 
  <? } ?> 
  </ul>  
</body> 
</html> 
You already noticed, we use "$this" in the template, so we need a class context to register variables and a small function to quote content called "q". So let's create a class that makes PHP templates as nice as Smarty templates:

Template.php
class Template { 
  function render($php) { 
    ob_start(); 
    include($php);
    return ob_get_clean();
  } 

  function __get($unused) { 
    return ''; 
  } 

  static function config($section, $key) { 
    static $config = null; 
    if ($config == null) include('core_conf.php'); 
    return isset($config[$section]) ?
      $config[$section][$key] : $config[$section]; 
  } 

  function c($section, $key) { 
    return self::config($section, $key); 
  } 
} 

function q($str) { 
  return htmlspecialchars($str, ENT_QUOTES); 
} 

With this small class we can write:
index.php
require 'Template.php';
$tpl = new Template(); 
$tpl->list = array('item1', 'item2', 'item3'); 
$tpl->description = 'Hello World!'; 
echo $tpl->render('main_tpl.php');
And we're done!

1 comment:

  1. This blog makes coding in php a really pleasure experience.
    Thanks thomas, you rock man.

    ReplyDelete

Labels

performance (23) benchmark (6) MySQL (5) architecture (5) coding style (5) memory usage (5) HHVM (4) C++ (3) Java (3) Javascript (3) MVC (3) SQL (3) abstraction layer (3) framework (3) maintenance (3) Go (2) Golang (2) HTML5 (2) ORM (2) PDF (2) Slim (2) Symfony (2) Zend Framework (2) Zephir (2) firewall (2) log files (2) loops (2) quality (2) real-time (2) scrum (2) streaming (2) AOP (1) Apache (1) Arrays (1) C (1) DDoS (1) Deployment (1) DoS (1) Dropbox (1) HTML to PDF (1) HipHop (1) OCR (1) OOP (1) Objects (1) PDO (1) PHP extension (1) PhantomJS (1) SPL (1) SQLite (1) Server-Sent Events (1) Silex (1) Smarty (1) SplFixedArray (1) Unicode (1) V8 (1) analytics (1) annotations (1) apc (1) archiving (1) autoloading (1) awk (1) caching (1) code quality (1) column store (1) common mistakes (1) configuration (1) controller (1) decisions (1) design patterns (1) disk space (1) dynamic routing (1) file cache (1) garbage collector (1) good developer (1) html2pdf (1) internationalization (1) invoice (1) just-in-time compiler (1) kiss (1) knockd (1) legacy code (1) legacy systems (1) logtop (1) memcache (1) memcached (1) micro framework (1) ncat (1) node.js (1) openssh (1) pfff (1) php7 (1) phpng (1) procedure models (1) ramdisk (1) recursion (1) refactoring (1) references (1) regular expressions (1) search (1) security (1) sgrep (1) shm (1) sorting (1) spatch (1) ssh (1) strange behavior (1) swig (1) template engine (1) threads (1) translation (1) ubuntu (1) ufw (1) web server (1) whois (1)