Trouble Shooting Wiki

Debugging Smarty Templates

From TroubleshootingWiki

Jump to: navigation, search
Smarty
Official Page
Project Documentation
Download
Source Book
Smarty PHP Template Programming and Applications
Smarty PHP Template Programming and Applications
ISBN 978-1-904811-40-4
Publisher Packt Publishing
Author(s) Joao Prado Maia, Lucian Gheorghe, Hasin Hayder

Contents

[edit] Debugging Templates

In this tutorial, you will learn how to troubleshoot common Smarty errors, and logical or semantic problems on your templates, and how to quickly get over these issues and get your productivity back. We will do that together by building a small set of pages, and fixing problems as they occur.

Error messages are not usually displayed to users when something goes wrong with their templates, because of the way Smarty is designed. Since Smarty parses templates and compiles them into PHP scripts, your PHP configuration dictates whether error or warning messages will be displayed to the user's browser. This is usually a very good thing as it will hide any problems that might be found on your templates, but it will also prevent you from debugging problems.

Hence, the first thing that is needed in order to debug Smarty templates is to enable the proper configuration settings in PHP to display error messages. Whenever these settings are enabled, Smarty will start displaying debugging messages automatically.

The objective now is to find the php.ini configuration file and change the lines that set the following directives:

  • error_reporting
  • display_errors

The location of the php.ini file depends on the operating system that you are using (if you are developing locally), or the operating system of the server running your web pages. Usually, the file can be found on C:\WINDOWS\php.ini on Windows systems, and /etc/php.ini on UNIX systems. If you don't have access to this file, ask your system administrator for help.

You will need to change the two directives to the following:

  • error_reporting = E_ALL
  • display_errors = On

Save the file and restart your web server. To make sure that the settings were properly updated, create a PHP script named phpinfo.php with the following content:

 <?php

phpinfo();
 ?>

Search the output for these two directives, and check if they are enabled.

By changing the configuration as described above, you are changing PHP's global configuration and because of that, these changes will apply to any other site that runs off the same web server. If this is not appropriate for you, you can also manually override these directives by including the following PHP snippet on your scripts:

 <?php

ini_set('display_errors', 1);

error_reporting(E_ALL);
 ?>

After performing the changes above, your PHP pages should display error messages correctly for you. However, be sure to remember to disable these settings when you are ready to go live with your pages.

[edit] Semantic Errors

Let's start our first foray into template debugging by creating a simple PHP script and an accompanying Smarty template. It will serve as a contact form for a fictitious company, but it will be a good start for our examples. Here are the files:

Create a file called index.php and put the following content in it:

 
<?php
 include_once('libs/Smarty.class.php');
 $smarty = new Smarty;
 
 $departments = array(
  'marketing' => 'Marketing Department',
  'sales' => 'Sales Department',
  'support' => 'Customer Service Department'
 );
 $smarty->assign('departments', $departments);
 
 $smarty->display('index.tpl');
 ?>

Create a new file called index.tpl with the following:

 <html>
 <head>
 <title>Example Corp.</title>
 </head>
 <body>
 <h3>Example Corp. - Contact Us</h3>
 
 <p>
  Please choose the department that you are trying to contact, and your
  contact details, and we will get back to you within 48 hours.
 </p>
 
 <form method="post" action="contact_handler.php">
 <table border="1">
  <tr>
  <td><b>Department:</b></td>
  <td>
  {foreach key="name" item="description" from=$department}
  <input type="radio" name="dept" value="{$name}"> {$description}<br />
  {/foreach}
  </td>
  </tr>
  <tr>
  <td><b>Your Details:</b></td>
  <td>
  <input type="text" name="details" size="40">
  </td>
  </tr>
  <tr>
  <td colspan="2">
  <b>Message:</b><br />
  <textarea name="message" style="width: 100%;"></textarea>
  </td>
  </tr>
  <tr>
  <td colspan="2"><input type="submit" value="Send Message"></td>
  </tr>
 </table>
 </form>
 
 </body>
 </html>

After opening the PHP script on your web browser, your output should look like:

As you can see from the screenshot on the facing page, something is clearly wrong. The template code we created should iterate over the list of available departments, and print each as a different radio box. However, nothing is being displayed. In this case, we first check if the PHP script is passing the correct values to the template. We find that it is indeed passing an associative array of department names and their descriptions.

Next, we check if the Smarty template is using the proper variable name. Aha, there is indeed a problem here. The PHP script calls the list of department names $departments, but the Smarty template is using the unknown variable name $department instead. By changing the template file to reference the correct variable name, the actual department names will be displayed as shown:

[edit] Common Smarty Errors

Let's expand on our web page to maybe embed some JavaScript code on the page, so it can validate the values on the form prior to the user actually submitting them. The best way to do this is to trap the submission by setting an onSubmit JavaScript event handler on that form, and then checking the values from a function. Let's do that now by modifying the file index.tpl so that it contains the following:

 <html>
 <head>
 <title>Example Corp.</title>
 </head>
 <body>
 
 <h3>Example Corp. - Contact Us</h3>
 
 <p>
  Please choose the department that you are trying to contact, and your
  contact details, and we will get back to you within 48 hours.
 </p>
 

<script language="JavaScript">

<!--

function validateForm(f)

{

if (f.details.value == '') {

alert('Please enter your contact details.');

return false;

}

return true;

}

//-->

</script>
 
 <form method="post" action="contact_handler.php" onSubmit="return validateForm(this);">
 <table border="1">
  <tr>
  <td><b>Department:</b></td>
  <td>
  {foreach key="name" item="description" from=$departments}
  <input type="radio" name="dept" value="{$name}"> {$description}<br />
  {/foreach}
  </td>
  </tr>
  <tr>
  <td><b>Your Details:</b></td>
  <td>
  <input type="text" name="details" size="40">
  </td>
  </tr>
  <tr>
  <td colspan="2">
  <b>Message:</b><br />
  <textarea name="message" style="width: 100%;"></textarea>
  </td>
  </tr>
  <tr>
  <td colspan="2"><input type="submit" value="Send Message"></td>
  </tr>
 </table>
 </form>
 
 </body>
 </html>

This should be enough to trap the submission of the form when visitors forget to fill out their own contact information. Let's see what it looks like on the browser:


Oops, looks like something is wrong again. Notice, however, that this time there's actually some useful information displayed above. To begin with, we have a line number this time, so we can go directly to the template file and see what the problem is. Open index.tpl and go to the line number in which the error is indicated. It should look like this:

As you can see from the screenshot from my text editor above, line 17 is part of the JavaScript code that we just added to this template. The problem here is that we forgot to tell Smarty not to parse this block of the template for variables or normal template syntax, so Smarty thinks that the left brace is telling it to parse the JavaScript code, which gives us this nonsensical error message.

In order to fix this, add {literal} before the <script> tag, and add {/literal} after the closing </script> tag.

After making these changes, try opening the page again. The page should now work and look like the following:

The lesson here is to be careful when using braces on your HTML, since it is a character that means something important to Smarty. If you need to have normal braces on your pages, use {literal} to tell Smarty to ignore those portions of the page.

Now let's add another feature to our contact form, so that we have a radio button that defaults to being checked when a visitor opens the page. We will simply change the template file, and manually check on the {foreach} loop if we should check the radio button or not.

Open index.tpl again and put the following content in it:

 <html>
 <head>
 <title>Example Corp.</title>
 </head>
 <body>
 
 <h3>Example Corp. - Contact Us</h3>
 
 <p>
  Please choose the department that you are trying to contact, and your
  contact details, and we will get back to you within 48 hours.
 </p>
 
 {literal}
 <script language="JavaScript">
 <!--
 function validateForm(f)
 {
  if (f.details.value == '') {
  alert('Please enter your contact details.');
  return false;
  }
  return true;
 }
 //-->
 </script>
 {/literal}
 
 <form method="post" action="contact_handler.php" onSubmit="return validateForm(this);">
 <table border="1">
  <tr>
  <td><b>Department:</b></td>
  <td>

{strip}
  {foreach key="name" item="description" from=$departments}

<input type="radio" name="dept" value="{$name}" {if $name == 'marketing'}checked{/if}> {$description}<br />
  {/foreach}
  </td>
  </tr>
  <tr>
  <td><b>Your Details:</b></td>
  <td>
  <input type="text" name="details" size="40">
  </td>
  </tr>
  <tr>
  <td colspan="2">
  <b>Message:</b><br />
  <textarea name="message" style="width: 100%;"></textarea>
  </td>
  </tr>
  <tr>
  <td colspan="2"><input type="submit" value="Send Message"></td>
  </tr>
 </table>
 </form>
 
 </body>
 </html>

Now open your web browser again and see how it looks. The output will be something like this:

As you can see, one of our changes introduced a bug in the template that triggered this error message. Looks like we forgot to close the {strip} function with a {/strip} tag, hence the error above.

Let's fix the error message by changing index.tpl to the following:

 
<html>
 <head>
 <title>Example Corp.</title>
 </head>
 <body>
 
 <h3>Example Corp. - Contact Us</h3>
 
 <p>
  Please choose the department that you are trying to contact, and your
  contact details, and we will get back to you within 48 hours.
 </p>
 
 {literal}
 <script language="JavaScript">
 <!--
 function validateForm(f)
 {
  if (f.details.value == '') {
  alert('Please enter your contact details.');
  return false;
  }
  return true;
 }
 //-->
 </script>
 {/literal}
 <form method="post" action="contact_handler.php" onSubmit="return validateForm(this);">
 <table border="1">
  <tr>
  <td><b>Department:</b></td>
  <td>
  {strip}
  {foreach key="name" item="description" from=$departments}
  <input type="radio" name="dept" value="{$name}" {if $name == 'marketing'}checked{/if}> {$description}<br />
  {/foreach}

{/strip}
  </td>
  </tr>
  <tr>
  <td><b>Your Details:</b></td>
  <td>
  <input type="text" name="details" size="40">
  </td>
  </tr>
  <tr>
  <td colspan="2">
  <b>Message:</b><br />
  <textarea name="message" style="width: 100%;"></textarea>
  </td>
  </tr>
  <tr>
  <td colspan="2"><input type="submit" value="Send Message"></td>
  </tr>
 </table>
 </form>
 
 </body>
 </html>

We simply added {/strip} after the {/foreach} tag. Now let's see if the error message goes away:

Beautiful, we should be good to go!

[edit] Other Common Smarty Errors

While the errors above are pretty common, the following are not the kind of errors related to your template coding practices, nor PHP configuration settings. Rather, they are related to system configuration issues, like permission bits being insufficient to open a file or a directory.

  • Warning: Smarty error: unable to read resource: "extra.tpl": In order to fix this type of error, make sure that the permission bits associated with the file are the appropriate ones for your website. That is, the web server that handles your pages needs to be able to access this file. Also, there might be a typo on the filename that causes this error.
  • Fatal error: Smarty error: unable to write to $compile_dir: Smarty works with your templates by parsing them, and then it compiles the templates into PHP scripts to improve efficiency. That is, instead of having to parse the template each time your PHP script is requested, it will compile the template into a PHP version of it, and skip the parsing routine. It will usually only re-compile the template if it needs to, such as when the template file is modified. The error message above is related to this feature. The compiled templates directory (referenced as $compile_dir within Smarty) which is usually called templates_c needs to be configured in such a way that the web server is allowed to write new files to it. To fix this error, set the proper permission bits to the templates_c sub-directory.

[edit] Smarty Debug Console

Another very interesting Smarty feature that is relevant to template designers is the Debug Console. This is a feature that is totally informational, which can be used to debug problems on your templates. It's important to note that the Debug Console will only work when the display() function call is used for a template. If the PHP script is using fetch() instead to grab the HTML output, Smarty will not include the Debug Console on that.

In order to enable this feature, you will need to update the index.php script we have created throughout this tutorial. Here's what the new content of index.php is supposed to be:

 <?php
 include_once('libs/Smarty.class.php');
 $smarty = new Smarty;

$smarty->debugging = TRUE;
 
 $departments = array(
  'marketing' => 'Marketing Department',
  'sales' => 'Sales Department',
  'support' => 'Customer Service Department'
 );
 $smarty->assign('departments', $departments);
 
 $smarty->display(index.tpl');
 ?>

When the $smarty->debugging flag is set to TRUE, and you open your PHP script on your browser, a pop-up window will be opened automatically with the Debug Console, and it should look like this:

Make sure that your browser is not blocking pop-up windows from your website; otherwise the Debug Console will never be displayed.

[edit] Summary

Smarty provides a huge list of features that are designed to help you while creating your templates, but that comes at a price complexity. While Smarty is a bit more complex than your usual templating engine, its features are well worth it. We covered a few of the most common Smarty problems, and quick ways to get past them.

While you create your templates, keep in mind that the more complex they are the harder it will be to debug problems with them; so always strive to keep your templates as simple as possible. Whenever you need to debug something, remember to use the Debug Console if possible.

[edit] Additional References

  • For instructions on Designing Smarty Templates, click here
  • For instructions on Installing Smarty, click here

[edit] Source

The source of this content is Chapter 7: Debugging for Designers of Smarty PHP Template Programming and Applications by Joao Prado Maia, Lucian Gheorghe and Hasin Hayder (Packt Publishing, 2007).