For last several months I have been developing a project using PHP and Smarty. The application is developed as Facebook application. As you may know Facebook changed their views and decided to motivate developers switching to iframe-based applications. So I did it… It’s hard to say all pros and cons switching from fmbl-based app to iframe-based one. Here I want to focus only on one problem of the bunch I had.

When I develop a fbml application I often don’t see an application output. I just get requests from Facebook, do some actions and send data to Facebook. Then Facebook transforms it somehow and I see the result. A very good result because Facebook does it well. With iframe-based application I see my problems much easier. I just open my iframe in a new tab, run YSlow or Page Speed, have a bunch of errors and try to fix them. Images, stylesheets, scripts from the same domain, missing headers, compressions and etc… It’s easy enough. But how can I deal with minify html in Smarty?

So… How can you fix it? Of course my first thought was a stupid one. I just have to remove unnecessary spaces and break lines in my templates when I deploy an application. It may work but your code always is dirty on the production server. It could be a nightmare when you have to do hotfix right on the production and commit the changes. Definitely, it would be a pain.

My second solution was using {strip} tag. It looks simple. Open {strip} before a header and close it after a footer. But what about ajax responses? I send some html thought ajax and I really don’t want to mess with {strip}.

After small research I was looking at Smarty output filter and it looked like a good solution. I just had to create a function removing unnecessary spaces and break lines and register it as output filter. Something like

<?php
function strip_output($output, &$smarty) {
  //.....
  return $newOutput;
 }
 $smarty->register_outputfilter('strip_output');
?>

I used Compactor class from Yii framework to implement strip_output function. It looks like

<?php
function strip_output($output, &$smarty) {
    $options = array(
        'compress_css' => true, 
        'strip_comments' => true, 
        'keep_conditional_comments' => true, 
        'compress_horizontal' => true, 
        'compress_vertical' => true, 
        'compress_scripts' => false, 
        'line_break' => PHP_EOL, 
        'preserved_tags' => array('textarea', 'pre', 'script', 'style', 'code'),
        'script_compression_callback' => false,
        'script_compression_callback_args' => array(),
    );
    $compactor = new Compactor($options);
    return $compactor->squeeze($output);
}
?>

It works well enough for full-page and ajax requests. But I really don’t want my server be overloaded by processing the html output in the runtime. I studied the Smarty API again and found the solution which works well for me. Smarty has postfilters which run through the templates after they are compiled. It was awesome because I had to change only one line of my previous code.

<?php
 function strip_output($output, &$smarty) {
  //.....
  return  $compactor->squeeze($output);
 }

 /*$smarty->register_outputfilter('strip_output');*/
 $smarty->register_postfilter('strip_output'); 
?>

It’s simple and great. I have less outgoing traffic from the server and users get the data faster because each page reduces its’ size by 20 percents.

P.S. You may get a problem with this solution when you run it on your existing project. You’ve implemented it but outputs don’t change. To fix it you have to remove all files in your template_c folder. Also I recommend you to create a task for this into your deployment script.