7.3 Packages

In this section, we discuss the optional packages that are available with PEAR, how to find out about them, how to find new ones, and how to install the ones you need. However, our focus is the optional HTML Integrated Template (IT) package , which is used to separate HTML presentation from PHP code. We show you how to use templates in an application, present working examples, and detail the key functions from the package and its extended child ITX templates. A longer template case study is presented in Chapter 16.

After our discussion of the IT package, we list the other packages that are available, and point to where selected packages are used in other chapters of this book.

7.3.1 Installing, Upgrading, and Understanding Packages

This section describes how to install and upgrade PEAR packages, and how to find out more information about them. For Unix platforms, including Mac OS X, the instructions are valid for PHP 4.3.0 or later versions. For Microsoft Windows, PEAR installation and upgrade is available after PHP 4.3.2.

7.3.1.1 Finding out about packages

At the time of writing, the PEAR documentation available at http://pear.php.net/manual/en/ was incomplete. However, you'll find some useful information there, particularly about the core components and a handful of the popular optional packages.

To go beyond the limited documentation, the first step is to access the package browser at http://pear.php.net/packages.php or search for a known package directly at http://pear.php.net/package-search.php. You can also access the same information using the PEAR installer, as described later in this section. This process provides you with concise information that sums up a package, and often a link to the project's homepage that may contain more details and code examples.

To begin to use a package, the best approach is to install it, review the source code of the package, and read any relevant postings to the php.pear.general newsgroup which is accessible at http://news.php.net/. To review the source code, you can follow two approaches: first, visit the source at http://cvs.php.net/cvs.php/pear/; or, second, view it on your system after the install process using the approach described later in this section. This process can sometimes be laborious but it's worth remembering that many of these packages are new, emerging, and supported to different degrees by their development teams. Reading source code is definitely worthwhile.

7.3.1.2 Using the PEAR installer

You need an Internet connection to complete this section.

As we discussed previously, a list of the packages installed with your PHP installation can be obtained at a shell prompt in a Unix system (when you're logged in as root) using:

% pear list

On a Microsoft Windows platform, you do this in a command window with:

C:\> pear.bat list

In the remainder of this section, we only list the Unix commands and show a Unix shell prompt. To use the command in Microsoft Windows, replace pear with pear.bat.

To find out about one of the packages installed on your system, you can ask for details or visit the package browser at http://pear.php.net/packages.php. For example, to find out more about the HTML_Template_IT package type:

% pear info HTML_Template_IT

In response, you'll get a page of information that describes the package, its current release, licensing requirements, and its release state. The release state is one of Stable, Beta, Alpha, or Devel(opment). The majority of packages are Stable, with the remaining majority in Beta testing. Use non-stable packages with caution.

If your computer has an Internet connection, you can check whether your packages can be upgraded to later releases by typing:

% pear list-upgrades

This requests information from the pear.php.net server. In response, the pear installer will report information such as:

Available Upgrades (stable):

============================

+-------------+---------+--------+

| Package     | Version | Size   |

| Archive_Tar | 1.0     | 12.4kB |

| Mail        | 1.0.2   | 12.1kB |

| Net_SMTP    | 1.1.2   | 5.2kB  |

| PEAR        | 1.0.1   | 75kB   |

| XML_Parser  | 1.0.1   | 4.9kB  |

You can obtain the same information by browsing the packages at the PEAR web site http://pear.php.net/.

All information is for stable releases of packages, which can be safely installed and used. You can choose to upgrade a specific package or upgrade all out-of-date packages. For example, to upgrade only the PEAR base class:

% pear upgrade PEAR

The PEAR installer retrieves the package and responds with:

downloading PEAR-1.0.1.tar ...

...done: 395,776 bytes

upgrade ok: PEAR 1.0.1

Sometimes, the upgrade process can fail but helpful information is provided as to why. For example, an upgrade of the Net_SMTP package often fails for PHP 4.3.2:

% pear upgrade Net_SMTP

downloading Net_SMTP-1.1.2.tar ...

...done: 29,184 bytes

requires package `Auth_SASL'

Net_SMTP: dependencies failed

In order to proceed, the Auth_SASL package is needed first. This can be achieved with:

% pear install Auth_SASL

You can then try again to install the Net_SMTP package using pear upgrade.

As discussed in the previous section, viewing source code is an excellent method to understand how a package works. After you've installed a package, you'll find it below the directory /usr/local/lib/php/ on most Unix systems, in /usr/local/php/lib/php under Mac OS X, or in C:\Program Files\EasyPHP1-7\php\pear\pear on a Microsoft Windows system if you've followed our PHP installation instructions in Appendix A to Appendix C. The majority of the core packages are in the directory itself, while the optional packages are stored in subdirectories that are named according to the package category. For example, the IT templates that are discussed in the next section are found in the HTML subdirectory. Other popular package categories are listed later in Section 7.3.3.

The PEAR installer isn't always reliable or well-configured on every system. If you have problems installing or upgrading packages, you can download packages from the PEAR web site and put them in the PEAR directories manually. This is also a useful trick for getting PEAR packages working without root or administrator user access: download the packages you need, uncompress them, put them in a directory that you've created, and then include the package file in your PHP script.

7.3.2 Using HTML Templates

Separating code from HTML can be difficult in PHP. As we discussed in Chapter 1 and have shown so far in this book, one of the best features of PHP is that scripts can be embedded anywhere in HTML documents. However, this can lead to maintenance problems: if you want to redesign the presentation of the web site, you may need to rewrite code or, at the very least, understand how PHP and HTML are interleaved in the application. This also makes it difficult to maintain code when it is interleaved with presentational components.

A good solution for medium- to large-scale web database applications is to use templates to separate markup and code. In this section, we illustrate how PEAR Integrated Templates (IT) can be used in PHP applications through simple examples, and also show you an example with Extended Integrated Templates (ITX).

There are many other good templating environments, including a few others in PEAR itself. Outside of PEAR, the Smarty PHP template engine is popular and flexible, and available from http://www.phpinsider.com/php/code/Smarty.

To use the IT and ITX packages, you need to install the package HTML_Template_IT . To do this, you can follow the general instructions in the previous section or the detailed instructions for Linux, Mac OS X, and Microsoft Windows platforms in Appendices A to C.

7.3.2.1 Working with blocks and placeholders

In our first example, we show you how to develop the basic components needed in most templated PHP code: an HTML template and its accompanying PHP script. Our aim in this example is to display a list of customers in an HTML table environment. The customer data is stored in a customer table in MySQL that was created with the following statement:

CREATE TABLE customer (

  cust_id int(5) NOT NULL,

  surname varchar(50),

  firstname varchar(50),

  initial char(1),

  title_id int(3),

  address varchar(50),

  city varchar(50),

  state varchar(20),

  zipcode varchar(10),

  country_id int(4),

  phone varchar(15),

  birth_date char(10),

  PRIMARY KEY (cust_id)

) type=MyISAM;

Example 7-2 is the template that acts as a placeholder to show selected customer information. In our example, the template is saved in the file example.7-2.tpl and stored in a templates directory below our main htdocs directory that contains the PHP scripts.

Perhaps the most surprising thing about a template is that it is usually well-formed HTML 4.01. Indeed, when it's viewed in a Mozilla browser as shown in Figure 7-1, it has the features of a customer listing but with only one row and with placeholders in curly braces shown instead of the customer details. We always use uppercase characters for our placeholders so that they stand out in the template and in the code, but this isn't required.

Placeholder and block names can consist of alphabetic and numeric characters, as well as underscores and hyphens. Spaces and other characters aren't allowed.

For blocks, a single space must precede and follow the keywords BEGIN and END, and a single space must follow the block name.


The other difference between a typical HTML page and a template is that the template contains comments that include the tags BEGIN and END. These comment tags are in pairs that have matching labels that define a block . In this example, there's one block that has the label CUSTOMER.

Blocks represent units of information that are optional or can repeat. In Example 7-2, the CUSTOMER block surrounds a prototype data row that is output once for each customer in the database. In our PHP script, we control the presentation by assigning each row of data from the database to the block, and then parsing and outputting the completed row as HTML to the browser.

Example 7-2. A template for displaying customer details
<!DOCTYPE HTML PUBLIC

                 "-//W3C//DTD HTML 4.01 Transitional//EN"

                 "http://www.w3.org/TR/html401/loose.dtd">

<html>

<head>

  <meta http-equiv="Content-Type" content="text/html; charset=iso-8859-1">

  <title>Customer Details</title>

<body>

<table>

<tr><th>Name<th>Address<th>City<th>State<th>Zipcode

<!-- BEGIN CUSTOMER -->

<tr><td>{FIRSTNAME} {SURNAME}<td>{ADDRESS}

    <td>{CITY}<td>{STATE}<td>{ZIPCODE}

<!-- END CUSTOMER -->

</table>

</body>

</html>

The template, as viewed in a Mozilla browser, is shown in Figure 7-1 (to view it, we renamed the .tpl file with an .html extension).

Figure 7-1. The customer template from Example 7-2 viewed in a Mozilla browser.
figs/wda2_0701.gif


The script that populates the template with the customer data is shown in Example 7-3. To access the DBMS, no new functionality is included: the script uses the query process explained in Chapter 6 to connect, query, and extract results. What is new is the use of templates: the script itself doesn't output data using print but instead assigns data to elements of the customer template.

Example 7-3. A PHP script that populates the customer template in Example 7-2
<?php

  require_once "HTML/Template/IT.php";

  include "db.inc";



  // Connect to the MySQL server

  if (!($connection = @ mysql_connect($hostname, $username, $password)))

     die("Cannot connect");



  if (!(mysql_select_db($databaseName, $connection)))

     showerror( );



  // Run the query on the connection

  if (!($result = @ mysql_query ("SELECT * FROM customer LIMIT 50",

                                 $connection)))

     showerror( );



  // Create a new template, and specify that the template files are 

  // in the subdirectory "templates"

  $template = new HTML_Template_IT("./templates");



  // Load the customer template file

  $template->loadTemplatefile("example.7-2.tpl", true, true);



  while ($row = mysql_fetch_array($result))

  {

     // Work with the customer block

     $template->setCurrentBlock("CUSTOMER");



     // Assign the row data to the template placeholders

     $template->setVariable("FIRSTNAME", $row["firstname"]);

     $template->setVariable("SURNAME", $row["surname"]);

     $template->setVariable("ADDRESS", $row["address"]);

     $template->setVariable("CITY", $row["city"]);

     $template->setVariable("STATE", $row["state"]);

     $template->setVariable("ZIPCODE", $row["zipcode"]);



     // Parse the current block

     $template->parseCurrentBlock( );

  }



  // Output the web page

  $template->show( );

?>

The code fragment:

require_once "HTML/Template/IT.php";

loads PEAR's Integrated Template class into the script. After this, we create a new IT template $template, and specify that the templates we're using are found in the templates subdirectory:

$template = new HTML_Template_IT("./templates");

(The period and forward slash in ./templates means the templates directory is a subdirectory of the directory that contains the PHP script.)

After that, we load in our template file from Example 7-2:

$template->loadTemplatefile("example.7-2.tpl", true, true);

The two additional parameters are discussed later in this section.

Having set up our template, we can now use it with the data from our query. This is a three-step process:

  1. Select the block to work with; in this example, there's only the CUSTOMER block.

  2. Assign data to the placeholders within the block.

  3. Parse the block.

This process is repeated each time we want to output a block (which, in this case, is a row of customer data). By default, if you don't use a block, it's assumed you don't want to output it and it isn't included in the HTML output.

In our script, the repeating three-step process is encapsulated in the following code fragment:

// Work with the customer block

$template->setCurrentBlock("CUSTOMER");



// Assign the row data to the template placeholders

$template->setVariable("FIRSTNAME", $row["firstname"]);

$template->setVariable("SURNAME", $row["surname"]);

$template->setVariable("ADDRESS", $row["address"]);

$template->setVariable("CITY", $row["city"]);

$template->setVariable("STATE", $row["state"]);

$template->setVariable("ZIPCODE", $row["zipcode"]);



// Parse the current block

$template->parseCurrentBlock( );

The parameter to HTML_Template_IT::setCurrentBlock( ) is the name of the block you want to work with in the template file. The parameters to HTML_Template_IT::setVariable( ) are a placeholder name within the block, and the data to assign to the placeholder. The method HTML_Template_IT::parseCurrentBlock( ) processes the currently selected block.

The script repeats the three-step process until there's no more data to process from the query. After that, the entire web page is output by the statement:

$template->show( );

The result of running the script and using the template is shown in Figure 7-2.

Figure 7-2. The output of running Example 7-3 shown in a Mozilla web browser
figs/wda2_0702.gif


7.3.2.2 Nested blocks

Example 7-4 shows a more complex template example. This template is designed to display information about wine regions and, for each region, a list of the wineries that are situated there.

We use two database tables in our example, winery and region. These are created with the following statements:

CREATE TABLE winery (

  winery_id int(4) NOT NULL,

  winery_name varchar(100) NOT NULL,

  region_id int(4) NOT NULL,

  PRIMARY KEY (winery_id),

);



CREATE TABLE region (

  region_id int(4) NOT NULL,

  region_name varchar(100) NOT NULL,

  PRIMARY KEY (region_id),

);

There's a one-to-many relationship between the tables: each winery row has a region_id attribute that stores the identifier of a row in the region table.

The blocks in the template in Example 7-4 are nested. The REGION block spans most of the HTML listing and contains within it a WINERY block. The nesting matches the table relationship: there can be many region blocks, and many winery blocks within each region.

Example 7-4. A template with nested blocks for showing regions and wineries
<!DOCTYPE HTML PUBLIC

                 "-//W3C//DTD HTML 4.01 Transitional//EN"

                 "http://www.w3.org/TR/html401/loose.dtd">

<html>

<head>

  <meta http-equiv="Content-Type" content="text/html; charset=iso-8859-1">

  <title>Regions and Wineries</title>

<body>

<ul>

<!-- BEGIN REGION -->

<li>Region: {REGIONNAME}

<ul>

<!-- BEGIN WINERY -->

<li>{WINERYNAME}.

<!-- END WINERY -->

</ul>

<!-- END REGION -->

</ul>

</body>

</html>

Sample output from Example 7-4 is shown in Figure 7-3.

Figure 7-3. The output of running Example 7-4 shown in a Mozilla web browser
figs/wda2_0703.gif


Example 7-5 shows the PHP script that works with the template. The logic of the script flows similarly to the template. The three-step process of selecting a block, assigning data to placeholders, and parsing is repeated for each region in the database. Nested inside that looping process, the same three steps occur for the wineries within each region.

One simple rule needs to be followed when a nested template is used: the innermost block must be parsed first, followed by the second innermost block, and so on until the outermost block has been parsed. In our example, this means that each repeating WINERY block must be parsed before the REGION block it belongs in. After all blocks that need to be populated have been parsed, the web page is output using HTML_Template_IT::show( ).

Example 7-5. The PHP script that works with the template in Example 7-4
<?php

  require_once "HTML/Template/IT.php";

  require "db.inc";



  if (!($connection = @ mysql_connect($hostname, $username, $password)))

     die("Cannot connect");



  if (!(mysql_select_db($databaseName, $connection)))

     showerror( );



  if (!($regionresult = @ mysql_query ("SELECT * FROM region LIMIT 10",

                                       $connection)))

     showerror( );



  $template = new HTML_Template_IT("./templates");

  $template->loadTemplatefile("example.7-4.tpl", true, true);



  while ($regionrow = mysql_fetch_array($regionresult))

  {

     $template->setCurrentBlock("REGION");

     $template->setVariable("REGIONNAME", $regionrow["region_name"]);



     if (!($wineryresult = 

         @ mysql_query ("SELECT * FROM winery

                         WHERE region_id = {$regionrow["region_id"]}",

                         $connection)))

        showerror( );



     while ($wineryrow = mysql_fetch_array($wineryresult))

     {

        $template->setCurrentBlock("WINERY");

        $template->setVariable("WINERYNAME", $wineryrow["winery_name"]);

        $template->parseCurrentBlock( );

     }

     $template->setCurrentBlock("REGION");

     $template->parseCurrentBlock( );

  }

  $template->show( );

?>

Make sure you remember to use HTML_Template_IT::setCurrentBlock( ) to select the block before you call either HTML_Template_IT::setVariable( ) or HTML_Template_IT::parseCurrentBlock( ). Failing to do so can cause unpredictable results and difficult-to-detect errors.

Also, be careful that you don't have two blocks with the same name. Unpredictable results are likely.


7.3.2.3 Preserving and removing blocks

In our previous example, we used the following fragment to load a template file:

$template->loadTemplatefile("example.7-4.tpl", true, true);

The second and third parameters specify sensible default behavior for working with unused placeholders and blocks. The second parameter specifies that if a block isn't used in a template, it shouldn't be output. This is useful if you have an optional block that that's sometimes used, as we discuss in the next section. The third parameter behaves similarly for placeholders: when set to true, placeholders that haven't had data assigned to them are removed during parsing.

If you have chosen to remove empty blocks but need to preserve a block at runtime, this is possible using the HTML_Template_IT::touchBlock( ) method. Touching means a block is marked as needing to be output, even if nothing has been assigned to its placeholders. For example, to preserve a DETAILS block you can use:

$template->touchBlock("DETAILS");

This is a useful feature in two situations: first, when you want to output a block but don't want to assign data to its placeholders; or, second, if a block has no placeholders and you want it to be shown. We show you an example in the next section.

7.3.2.4 More on nesting and optional blocks

Blocks aren't always nested: if data isn't related, it shouldn't be nested. For example, if we wanted to output information about the ten most popular wineries and the ten best customers, we might use the following template:

<!DOCTYPE HTML PUBLIC

                 "-//W3C//DTD HTML 4.01 Transitional//EN"

                 "http://www.w3.org/TR/html401/loose.dtd">

<html>

<head>

  <meta http-equiv="Content-Type" content="text/html; charset=iso-8859-1">

  <title>Details</title>

<body>

<h1>Our best customers</h1>

<!-- BEGIN CUSTOMER -->

Name: {FIRSTNAME SURNAME}

<!-- END CUSTOMER -->

<h1>Our most popular wineries</h1>

<!-- BEGIN WINERY -->

Name: {WINERYNAME}

<!-- END WINERY -->

</body>

</html>

In this structure, we can choose to repeat the CUSTOMER block zero or more times, and to independently repeat the WINERY block zero or more times. There is no relationship between the two blocks, and it doesn't matter whether you work with the customers or wineries first. Unrelated, unnested blocks can be assigned and parsed in any order. However, regardless of how you process and assign the data, all CUSTOMER blocks will always appear before all WINERY blocks because that's how the template is structured.

In the previous example, if you don't assign any data to the CUSTOMER block, the heading Our best customers will still be output because it isn't part of a block that you can control in your code. Moving the heading inside the CUSTOMER block doesn't solve the problem because the heading would then be repeated for each customer. One solution is to add another unnested block to the template so that the heading is optional:

<!DOCTYPE HTML PUBLIC

                 "-//W3C//DTD HTML 4.01 Transitional//EN"

                 "http://www.w3.org/TR/html401/loose.dtd">

<html>

<head>

  <meta http-equiv="Content-Type" content="text/html; charset=iso-8859-1">

  <title>Details</title>

<body>

<!-- BEGIN CUSTOMERHEADING -->

<h1>Our best customers</h1>

<!-- END CUSTOMERHEADING -->

<!-- BEGIN CUSTOMER -->

Name: {FIRSTNAME SURNAME}

<!-- END CUSTOMER -->

<h1>Our most popular wineries</h1>

<!-- BEGIN WINERY -->

Name: {WINERYNAME}

<!-- END WINERY -->

</body>

</html>

You can then use program logic to choose whether to output a CUSTOMERHEADING or not, depending on whether there are any CUSTOMER blocks being used. Note, however, that the CUSTOMERHEADING block doesn't contain any placeholders, and so with the default behavior you'll need to call $template->touchBlock("CUSTOMERHEADING") so that it's displayed in the output.

Our previous example can be improved. To avoid having to use program logic and the HTML_Template_IT::touchBlock( ) method, you can restructure the template so that it's nested:

<!DOCTYPE HTML PUBLIC

                 "-//W3C//DTD HTML 4.01 Transitional//EN"

                 "http://www.w3.org/TR/html401/loose.dtd">

<html>

<head>

  <meta http-equiv="Content-Type" content="text/html; charset=iso-8859-1">

  <title>Details</title>

<body>

<!-- BEGIN CUSTOMERHEADING -->

<h1>Our best customers</h1>

<!-- BEGIN CUSTOMER -->

Name: {FIRSTNAME SURNAME}

<!-- END CUSTOMER -->

<!-- END CUSTOMERHEADING -->

<h1>Our most popular wineries</h1>

<!-- BEGIN WINERY -->

Name: {WINERYNAME}

<!-- END WINERY -->

</body>

</html>

This works better because the CUSTOMERHEADING block contains the CUSTOMER block. With nesting, if the CUSTOMER block is used, there's no need to use HTML_Template_IT::touchBlock( ) on CUSTOMERHEADING. Similarly, if nothing is assigned to a CUSTOMER block, CUSTOMERHEADING hasn't been touched and won't be output. This is another example of our basic relationship rule: if data is related, use nesting; if it isn't, don't.

So far, we've dealt with related and unrelated blocks that appear in a fixed order. Sometimes, however, you may want to display data in an arbitrary order that you want to be flexible at runtime. To do this, you can create a block that contains several nested blocks at the same level. For example, if we wanted to output several red, green, or blue messages in any order on a page, we could use the following template:

<!DOCTYPE HTML PUBLIC

                 "-//W3C//DTD HTML 4.01 Transitional//EN"

                 "http://www.w3.org/TR/html401/loose.dtd">

<html>

<head>

  <meta http-equiv="Content-Type" content="text/html; charset=iso-8859-1">

  <title>Color lines</title>

<body>

<!-- BEGIN COLORLINES -->

<!-- BEGIN RED -->

<font color="red">{MESSAGE}</font>

<!-- END RED -->

<!-- BEGIN GREEN -->

<font color="green">{MESSAGE}</font>

<!-- END GREEN -->

<!-- BEGIN BLUE -->

<font color="blue">{MESSAGE}</font>

<!-- END BLUE -->

<!-- END COLORLINES -->

</body>

</html>

So, to output a blue line, you select the BLUE block, assign the data to MESSAGE placeholder, parse the BLUE block, and then select and parse the COLORLINES block. To output another color, you repeat the same process for that different colored block. Using this technique, the COLORLINES block repeats, but with each repeat you can choose a different inner block. In Chapter 10 and Chapter 16, we explain a template for displaying form widgets that uses this technique.

7.3.2.5 Extended Integrated Templates (ITX)

Optional blocks allow most of the flexibility you'll need to develop template applications. However, sometimes you may need to dynamically create a template at runtime. Usually, this is done by using a main template file, and then adding template fragments in the PHP script. A popular use of this technique is to store a standard header and footer for an application in a main template file, and then to dynamically add the page body at runtime. This is what we do in our sample application in Chapter 16 through Chapter 20.

The Extended Integrated Template (ITX) class extends IT templates, adding the functionality to dynamically construct templates at runtime. The following is an example main template file stored in the file about_today.tpl:

<!DOCTYPE HTML PUBLIC

                 "-//W3C//DTD HTML 4.01 Transitional//EN"

                 "http://www.w3.org/TR/html401/loose.dtd">

<html>

<head>

  <meta http-equiv="Content-Type" content="text/html; charset=iso-8859-1">

  <title>About Today</title>

</head>

<body>

{MESSAGE}

</body>

</html>

The placeholder MESSAGE is the position at which our choice of template fragment is inserted. In this example, our script will insert a different template depending on the day of the week. If today is a weekday, the following template fragment stored in the file weekday.tpl is inserted:

Oh no. It's {DAY}, which is a weekday.

If today is on a weekend, this fragment stored in the file weekend.tpl is inserted:

Good news. It's {DAY}, which is on the weekend.

All of the template files are stored in the same directory.

The script that works with the templates is as follows:

<?php

  require_once "HTML/Template/ITX.php";



  $template = new HTML_Template_ITX('.');

  $template->loadTemplatefile("about_today.tpl", true, true);



  $daynumber = date("w");



  // Is it a weekday?

  if ($daynumber != 0 && $daynumber != 6)

     // Include the weekday template fragment

     $template->addBlockFile("MESSAGE", "NEWMESSAGE", "weekday.tpl");

  else

     // Include the weekend template fragment

     $template->addBlockFile("MESSAGE", "NEWMESSAGE", "weekend.tpl");



  $template->setCurrentBlock("NEWMESSAGE");

  $template->setVariable("DAY", date("l"));

  $template->parseCurrentBlock( );

  $template->show( );

?>

Rather than work with IT.php library, this script uses the ITX.php file. The ITX templates provide several new methods, the most useful of which is HTML_Template_ITX::addBlockFile( ). This method takes three parameters: the placeholder to replace, the name of the block to replace it with, and the template fragment file that forms the body of the block.

In our example, depending on the day of week determined with the date( ) function, a choice is made as to whether to replace the MESSAGE placeholder with the fragment weekday.tpl or the fragment weekend.tpl; the date( ) function is discussed in Chapter 3. After the replacement, the script proceeds in the same way as previous examples by selecting our new block, assigning values to placeholders, parsing, and outputting the results. The template fragments do not include the name of the new block, this is supplied as the second parameter to HTML_Template_ITX::addBlockFile( ).

As we've shown you, the HTML_Template_ITX::addBlockFile( ) inserts a file into a template at a location defined by a placeholder and then redefines the replaced section as a block. Blocks can also be replaced at runtime by other blocks using the HTML_Template_ITX::replaceBlockFile( ) method that's explained in the next section.

7.3.2.6 Essential IT and ITX functions

v oid HTML_Template_IT::HTML_Template_IT ([string root])

This is the constructor for the HTML_Template_IT class. It is called to create a new template and takes an optional root directory as a parameter. If the root directory is provided, the template file that is loaded with HTML_Template_IT::loadTemplateFile( ) is assumed to be based in this directory. (The return type of void means that the method does not return a value.)


Boolean HTML_Template_ITX::addBlock(string placeholder, string block, string template)

Replaces a placeholder in the current template with a block that is stored in the template file. The template file should not contain the block BEGIN and END tags: these are created by the method and associated with the block name.


array HTML_Template_ITX::blockExists(string block)

Returns true if the block exists and false otherwise.


array HTML_Template_ITX::BlockvariableExists(string placeholder)

Returns true if the placeholder exists and false otherwise.


string HTML_Template_IT::get([string block])

Returns a block after all placeholders have been replaced. If a parameter isn't supplied, the entire template is returned. In most applications, the template is output using HTML_Template_IT::show( ) rather than returned with this method. However, this method can be used, for example, to produce template-based emails (as used in Chapter 19) or textual reports.


array HTML_Template_ITX::getBlockList( )

Returns a list of template block names in a one-dimensional array.


array HTML_Template_ITX::getBlockVariables(string block)

Returns a list of block placeholder names in a one-dimensional array.


Boolean HTML_Template_IT::loadTemplateFile(string file [, Boolean removeVars [, Boolean removeBlocks]])

Reads a template file from disk. The directory is a concatenation of any root directory supplied to the constructor plus the file provided. If removeVars is true, unassigned placeholders are deleted from the output. If removeBlocks is set to true, unused blocks are removed except if the block has been accessed with HTML_Template_IT::touchBlock( ). Both optional parameters are set to true by default. Returns true on success and false on failure.


void HTML_Template_IT::parse ([string block])

Process a block by replacing all placeholders with their assigned values. If no parameter is supplied, the entire template is parsed. Child blocks should be parsed before their parents, that is, blocks should be processed from most- to least-nested.


void HTML_Template_IT::parseCurrentBlock ( )

Process the current block selected with HTML_Template_IT::setCurrentBlock( ) by replacing all placeholders with their assigned values. Child blocks should be parsed before their parents, that is, blocks should be processed from most- to least-nested.


string HTML_Template_ITX::placeholderExists(string placeholder [, string block])

Returns the name of the first block that contains the placeholder in the template or in an optional block. If no block contains the placeholder, the empty string is returned.


Boolean HTML_Template_ITX::replaceBlock(string block, string file [, Boolean preserve])

Replaces a block in the current template with a block of the same name that is stored in a file. The file should not contain the block BEGIN and END tags: these are created by the method. The existing assignments to placeholders can be preserved if the optional parameter preserve is set to true; by default it is false. Returns true on success and false on failure.


Boolean HTML_Template_IT::setCurrentBlock ([string block])

Makes a block the currently selected block. If no parameter is provided, no block is set but instead any placeholders that are outside of blocks are made current; all of our examples use only placeholders inside blocks, but several examples without blocks are in later chapters. Returns true on success and false on failure.

A call to this method should be made prior to assigning variables to placeholders with HTML_IT_Template::setVariable( ).


void HTML_Template_IT::setVariable(string placeholder, string variable)

Assign a variable to the placeholder in the currently selected block. Blocks are selected with HTML_Template_IT::setCurrentBlock( ).

The function has an alternate, array parameter that isn't useful for the majority of applications, and we ignore it here.


void HTML_Template_IT::show([string block])

Outputs a block after all replacements have been made. Without the parameter, the complete template is output. In our examples, the parameter is not provided and this is the final step in working with the template.


Boolean HTML_Template_IT::touchBlock(string block)

Preserves an empty block in the output when no data has been assigned to its placeholders. This works even if the third parameter to HTML_Template_IT::loadTemplateFile( ) is set to true. Returns true on success and false on failure.

7.3.3 Optional Packages

Of the 154 PEAR packages at the time of writing, this section lists the 40 most popular as determined by download frequency at http://pear.php.net/package-stats.php. As discussed at the beginning of this section, the complete list is available by requesting the package installer to provide the information or by browsing packages in the repository. Selected packages are used in other sections of the book, and we've noted this next to those packages.

7.3.3.1 Authentication

There are six packages available, and two are popular.

  • Auth is a session-based authentication class that supports all PEAR DB DBMSs, as well as authentication for text files, LDAP servers, POP3 servers, IMAP servers, vpopmail accounts, RADIUS, and SOAP. Our authentication in Chapter 11 supports similar features.

  • Auth_HTTP provides methods for HTTP authentication. We discuss HTTP authentication in Chapter 11.

7.3.3.2 Benchmarking

There's only one package, and it's in the top 40.

  • Benchmark is a framework for benchmarking the performance of PHP functions and scripts. Its similar in style to the popular GNU C programming tool gprof.

7.3.3.3 Caching

Two packages are available, and one is popular.

  • Cache stores the results of previous function calls, script executions, and other activities so that they can be used in the future. Caching often speeds-up program execution if results or scripts are re-used frequently, and your web site is under high load.

7.3.3.4 Console

Five packages are available. The popular one is the core component Console_Getopt for retrieving command-line arguments from non-web scripts.

7.3.3.5 Database

There are fourteen packages, of which four are popular.

  • DB is a core component described in its own section in this chapter.

  • DB_DataObject is an SQL builder and object interface to database tables.

  • DB_Pager retrieves data in chunks after a query using PEAR DB. The aim is to allow you to retrieve and display data for subsequent display in pages.

  • MDB is a merging of PEAR DB and Metabase; Metabase is an alternative to PEAR DB. The MDB package provides a superset of the functionality of PEAR DB.

7.3.3.6 Date

There is one package that's popular.

  • Date is classes for manipulating and working with dates and time zones without timestamps, and without year range restrictions. We use Date in Chapter 9.

7.3.3.7 Filesystem

There are six packages, of which two are popular.

  • Archive_Tar supports creating, listing, extracting, and adding to tar (Unix archive) files, a common format of zip-like archives on Unix-style systems. This is a core component of PEAR that's used by the installer.

  • File provides methods to read and write files, and to deal with paths. It also provides an interface for working with comma-separated value (CSV) files.

7.3.3.8 HTML

There are fifteen packages, including five popular ones.

  • HTML_QuickForm for creating, processing, and validating HTML form environments. We develop our own framework for creating template-based forms in Chapter 16.

  • HTML_Table for developing, manipulating, and reusing HTML <table> environments.

  • HTML_Template_IT is a templating environment described in its own section in this chapter. It includes the extended template package ITX.

  • HTML_TreeMenu creates attractive menus for display using JavaScript at the client. We discuss developing simple menus using JavaScript in Chapter 9.

  • Pager is a class for viewing data in pages with previous and next buttons. We develop our own approach to this in Chapter 17.

7.3.3.9 HTTP

There are six packages and three are popular.

  • HTTP is a core component discussed at the beginning of this chapter.

  • HTTP_Request is designed for easy formatting of HTTP requests, including all methods, basic authentication, proxy authentication, and redirection. We discuss HTTP in Appendix D, HTTP authentication in Chapter 11, and redirection in Chapter 6.

  • HTTP_Upload allows easy management of files uploaded from browsers to web servers using form environments.

7.3.3.10 Internationalization

There's one popular package for internationalization.

  • I18N is designed to help you localize applications by determining browser language, currency, date and time, and numbers.

7.3.3.11 Logging

There is one package, and it's popular.

  • Log is a logging system that can log data to many different targets including PEAR DB, files, and email.

7.3.3.12 Mail

There are six packages, and two are popular.

  • Mail is described in the core components section at the beginning of this chapter. It's used in Chapter 19.

  • Mail_Mime provides classes to encode and decode Mime-encoded attachments.

7.3.3.13 Networking

There are twenty-nine packages, of which four are popular: we use the Net_DNS package (which isn't discussed here) in Chapter 9.

  • Net_POP3 is a class for accessing POP3 mail servers.

  • Net_Socket is a core component for working with network sockets and is described at the beginning of this chapter.

  • Net_URL provides easy parsing of URLs, allowing components to be extracted without difficult string processing

  • Net_UserAgent_Detect determines the web browser, version, and platform from the HTTP headers.

7.3.3.14 PEAR

There are three packages and two are popular.

  • PEAR is a set of core classes described at the beginning of this chapter.

  • PEAR_Frontend_Web is a web interface to the PEAR package manager. We describe the command-line version in this chapter, but it's likely that this package will become popular for configuration on all platforms when it leaves the beta-testing phase.

7.3.3.15 PHP

There are nine packages and three are popular.

  • apd is a profiler and debugger that helps in optimizing code.

  • bcompiler allows you to protect your code by compiling it rather than distributing PHP source.

  • PHPDoc generates documentation from source code.

7.3.3.16 XML

There are eleven packages, of which three are popular.

  • XML_Parser is designed to parse XML.

  • XML_RPC is a core package that implements XML-RPC.

  • XML_Tree represents XML data as a tree structure.

7.3.3.17 Web services

There are three packages, of which one is popular.

  • SOAP is a client and server package for implementing Simple Object Access Protocol (SOAP) protocols and services. SOAP is an emerging standard, and a good introduction to SOAP is available at http://www.w3.org/TR/SOAP/.