You are here: WikiStart/Docs/FAQ


patTemplate FAQ

How can I create lists with the result of a database query?

Creating lists with patTemplate is quite easy, and it's even easier when you are using patTemplate in conjunction with patDbc! Let's take look at the template for a list:

<patTemplate:tmpl name="list">
<table border="1" cellpadding="10" cellspacing="0">
  <tr>
     <th>Superhero Name</th>
     <th>Realname</th>
     <th>Action</th>
  </tr>
  <!-- template for list row -->
  <patTemplate:tmpl name="list_entry">
  <tr>
     <td>{SUPERHERO}</td>
     <td>{REAL_NAME}</td>
     <td><a href="edit.php?id={ID}">edit</a></td>
  </tr>
  </patTemplate:tmpl>
</table>
</patTemplate:tmpl>

Now imagine you've got a mysql table with three columns: id, superhero and real_name and you'd like to display a list with all entries from the table in the template above.

<?PHP
$tmpl = new patTemplate();
$tmpl->setBasedir( "templates" );
$tmpl->readTemplatesFromFile( "superherolist.tmpl" );

$db = DB::connect('mysql://user:pass@localhost/myDb');

$query = "SELECT id, superhero, real_name FROM secretIdentities ORDER BY superhero";
$result = $db->getAll($query, DB_FETCHMODE_ASSOC);
$tmpl->addRows( "list_entry", $result);

$tmpl->displayParsedTemplate();
?>

Of course you can use any other database abstraction layer or native PHP functions for database access - we used PEAR::DB in this example. $db->getAll(...) just executes mysql_fetch_array() and collects all rows in one array that it returns. This array is just handed over to the template block list_entry using addRows(), and patTemplate automatically repeats this block, for the amount of rows contained in the array. This makes handling database results fun.

How can I create tables with several rows and columns?

This is a problem that often occurs, when you are creating lists with more than one columns? We refer to this problem as 'nested repetitions', as it's not only needed when creating to dimensional tables, but also nested lists. At first glance, it may seem quite hard, but once you've understood it, it's quite easy... At first, let's take a look at the template structure:

<table border="1" cellpadding="10" cellspacing="0">

  <!-- template for table row -->
  <patTemplate:tmpl name="row">
  <tr>

    <!-- template for table cell -->
    <patTemplate:tmpl name="cell">
    <td>{REAL_NAME} is {SUPERHERO}</td>
    </patTemplate:tmpl>

  </tr>
  </patTemplate:tmpl>

</table>

There are two templates, on called "row", which has to be repeated and one called "cell", which is repeated for all cells in each row. In these cells the content has to be displayed. To repeat the cells and the rows, use the following PHP code:

<?PHP
// data to display
$data = array(
               array( "real_name" => "Clark Kent", "superhero" => "Superman" ),
               array( "real_name" => "Bruce Wayne", "superhero" => "Batman" ),
               array( "real_name" => "Kyle Rayner", "superhero" => "Green Lantern" ),
               array( "real_name" => "Wally West", "superhero" => "The Flash" ),
               array( "real_name" => "Linda Danvers", "superhero" => "Supergirl" ),
             );
// number of columns per row
$cols  = 3;

// calculate number of rows
$rows = ceil(count($data)/$cols);
$counter = 0;

// loop for each row
for ($i = 0; $i < $rows; $i++) {
  // clear cells from last row
  $tmpl->clearTemplate( "cell" );

  // put data for one row in a new array 
  $rowData = array();
  for ($j = 0; $j < $cols; $j++) {
    if (isset($data[$counter]))
      array_push($rowData, $data[$counter++]);
  }
  // add the data of one row to the cells
  $tmpl->addRows( "cell", $rowData );
  // parse this row and append the data to previously parsed rows 
  $tmpl->parseTemplate( "row", "a" );
}
$tmpl->displayParsedTemplate();
?>

The most important function is parseTemplate( "row", "a" ), which parses a template and appends it to previously parsed contents of the template. This allows you to parse several rows.

Make use of array_chunk()

If you've already installed PHP 4.2.0 you may use array_chunk() to split the full data into arrays for each row.

How can I hide parts of a page?

Hiding parts of a page or displaying them only when a condition occured is quite easy. Just take a look at the following example:

<patTemplate:tmpl name="page">
<html>
  <head>
    <title>patTemplate Example</title>
  </head>
  <body>
  <!-- This template is hidden by default -->
  <patTemplate:tmpl name="secret" visibility="hidden">
    I know a secret: <b>Clark Kent is superman!</b>
  </patTemplate:tmpl>
  </body>
</html>
</patTemplate:tmpl>

This example consists of two templates: page and secret, which will not be displayed if you call displayParsedTemplate() after loading this templates. It will not be displayed because of the visibility="hidden" attribute. If you went to display the page template, including the secret template, you may do this by using a PHP method of the patTemplate class called setAttribute. This method takes three arguments, the first is the name of the template for which the attribute should be set. The second is the name of the attribute and the last is the value of the attribute. To change the visibility of a template, use the follwing PHP code:

<?PHP
$tmpl->readTemplatesFromFile( "myTemplate.tmpl" );

if( $knowSecret == "yes" )
  $tmpl->setAttribute( "secret", "visibility", "visible" );

$tmpl->displayParsedTemplate( "page" );
?>

How do I build a drop-down menu witha database result?

Dropdown menus that let you choose between different options that result from a database query are often needed when building web-pages. To create them using patTemplate is quit easy. Take a look at the following template:

<patTemplate:tmpl name="page">
<html>
  <head>
    <title>patTemplate Example</title>
  </head>
  <body>
    <table border="0">
      <tr>
        <td>Choose your superhero:</td>
        <td>
          <select size="1" name="superhero">
            <option value="none">Please choose...</option>
            <patTemplate:tmpl name="dropdown_entry" type="condition" conditionvar="selected">
              <patTemplate:sub condition="no">
                <option value="{ID}">{SUPERHERO}</option>
              </patTemplate:sub>
              <patTemplate:sub condition="yes">
                <option value="{ID}" selected="yes">{SUPERHERO}</option>
              </patTemplate:sub>
            </patTemplate:tmpl>
          </select>
        </td>
	  </tr>
    </table>
  </body>
</html>
</patTemplate:tmpl>

If you ignore the HTML code, the template is quite simple. Of course there is one template for the complete page, like it should be in every file. This template also contains the actual <select> tag, which craetes a HTML drop down menu. Furthermore there is a second template called dropdown_entry. This template will be used to dynamically build the drop down list. The template type is set to condition as there may be two modes for each entry. Eitherit is selected by default or it isn't. To fill the drop down menu with entries resulting from database query you'll need the following code:

<?PHP
$tmpl->readTemplatesFromFile( "myTemplate.tmpl" );

$defaultId =  19;

$query     =  "SELECT id, superhero FROM heroes ORDER BY superhero";
$result    =  mysql_query( $query );

$entries   =  array();
while ($row = mysql_fetch_array($result, MYSQL_ASSOC)) {
  // determine, wether entry should be selected by default
  if( $row["id"] == $defaultId )
    $row["selected"]  =  "yes";
  else
    $row["selected"]  =  "no";

  // add the entry to all other entries
  array_push( $entries, $row );
}
// add all entries to the drop down menu
$tmpl->addRows( "dropdown_entry", $entries );
// display the page
$tmpl->displayParsedTemplate( "page" );
?>

This will display a drop-down menu with all entries in the table heroes, the superhero with the id 19 will be selected by default.

Switching to radio groups

If you are using the technique of condition templates to print out to different versions for selected and unselected entries, you may switch the drop-down menu to a radio group without modifying the PHP code.

Can I re-use templates in different pages?

Of course you can. Let's say you'v got a footer and a header, which should be the same in all of your pages, so you have to change it only once and it will be updated in all pages. To accomplish this, at first create the two files, and save them to your template directory as header.tmpl and footer.tmpl. The templates could look like this:

<patTemplate:tmpl name="header">
  <h1>My Superhero database</h1>
</patTemplate:tmpl>

and this

<patTemplate:tmpl name="footer">
<hr/>
<span class="footer">Superhero database was last updated on 2001-12-24 (Oh, christmas).</span>
</patTemplate:tmpl>

Now you may include these two files in all other pages by using the src attribute of the <patTemplate:tmpl> tag:

<patTemplate:tmpl name="page">
<html>
  <head>
    <title>Any page of the superhero database</title>
  </head>
  <body>
    <patTemplate:tmpl name="includedHeader" src="header.tmpl" parse="on"/>
    Here is the rest of the page...
	Can be anything from static HTML to other templates.
    <patTemplate:tmpl name="includedFooter" src="footer.tmpl" parse="on"/>
  </body>
</html>
</patTemplate:tmpl>

You may adress the header and footer templates as if the were written directly into the page but you have to change them only once, so this is some kind of include() for templates.

Organizing templates in folders

Of course you may also organzize templates in subfolders. If you'd like to put the shared templates in a subfolder of your template folder, just use <patTemplate:tmpl src="shared/header.tmpl" parse="off">. patTemplate will then load the template from ./templates/shared/header.tmpl if your basedir is set to templates.