PHP DevCenter
oreilly.comSafari Books Online.Conferences.

advertisement


PHP and Heredocs
Pages: 1, 2

The HTML Side Of Things

At this point, we can assign chunks of text to PHP associative array variables by including external files which contain heredocs. We can expand variables within the assignments and can easily access the contents at runtime for debugging. Now that we have separated database calls from PHP classes, let's turn our attention to HTML.



There are several ways to separate the presentation of HTML from the logic of PHP, including Smarty, the well known template package. (Smarty has an extensive set of capabilities, and is worth exploring.) For this project, using heredocs and substituting database values for placeholders is sufficient and straightforward. Here is a simple HTML template file:

<?php
$template =<<<EOD_PD
<html>
<head>
<title>Photo Display: FP_PHOTO_ID...</title>
</head>
<body>
FP_TOOLBAR
<p>
<center>
<img src="FP_FULL" />
<br />
FP_CAPTION
</center>
</p>
</body>
</html>
EOD_PD
?>

In my project, this particular file is at (project_path)/include/ui-default/en/photo-display.php. I access the file within my PHP classes like this:

$display_photo_page = $this->get_template("photo-display.php");

where get_template() looks like:

function get_template($which_file)
{
    global $FP_LANG;
    global $FP_UI;

    include
    "/usr/local/php-files/include/$FP_UI/$FP_LANG/$which_file";
    
    return $template;
}

Once again, it's straightforward. I have a couple of variables which control the UI to display. My HTML UI could be simple or complex, depending on the end user and their browser. For every UI, I have the option of grabbing a template that matches the language being used on the browser side. You can look at ($_SERVER['HTTP_ACCEPT_LANGUAGE'] to find the language being used and default to something like en (for English) when nothing is set. Keeping security in mind, I do not take the values of $FP_LANG and $FP_UI directly from the user. Instead, I use user side information such as browser variables and cookie preferences as indexes into known good values.

The placeholders are consistent between languages and UIs. For this example, I used:

  • FP_PHOTO_ID, a unique photo id from the database;
  • FP_TOOLBAR, a snippet of HTML, used for navigation and pulled in from another HTML template file;
  • FP_FULL, a URL for a photo; and
  • FP_CAPTION, a photo caption.

Filling In The Template

At this point we have seen a method to set a $RSRC array, and our HTML template. The next steps are to

  • make a database call,
  • build an associative array with placeholders as keys and database fields as values,
  • do substitutions on the HTML template, and
  • print out the result.

In order to show these in context, here is a stripped down example from my production code. Here is a SQL call, defined in a resource file:

$RSRC['SQL_PHOTO_DISPLAY'] =<<<EOD
SELECT collection.collection_id AS collection_id,
	   collection.collection_dir AS collection_dir,
	   photo.comments AS comments
FROM  photo, collection
WHERE
	 photo_id = '{$VALS['photo_id']}'
AND  collection.collection_id = photo.collection_id;
EOD;

And here is the function that ties everything together:

/*
**    display - show a photo
**
**    $db - an object that contains a handle to a MySQL database
**    $photo_id - user input (i.e. 000045) via a link (GET)
*/
function display($db, $photo_id)
{
	$P = &$this;
	$RSRC = array();
	$VALS = array();
	
	$VALS['photo_id'] = $P->check_id($photo_id);
	$P->get_global_resources($RSRC, "d-photo.res", $VALS);
	
	// toolbar is just a simple HTML menu.  It gets substituted
	// into the main page later
	$toolbar            = $P->get_template("toolbar.php");
	$display_photo_page = $P->get_template("photo-display.php");
    
	// a sample debugging call.  Use tail -f on an Apache error_log
	// to see the output
	$P->p_dbg($RSRC, "photo display RSRC");
	
	// $db is an object with an open handle into our database
	$sql_result = $db->query($RSRC['SQL_PHOTO_DISPLAY']);
	$row        = mysql_fetch_assoc($sql_result);
	
	$collection_dir = $row['collection_dir'];
	
	/*
	** in real code, we ask the database for the filetype, and
	** map to a filename extension from that... here we're
	** just coming up with a relative path, based on
	** the collection directory and photo id.
	*/
	$photo_path = $P->get_web_fullsize($collection_dir) .
						$VALS['photo_id'] . ".jpg";
                      
	// here is how we build up an array of replacements
	// that will be done on the HTML template
	$all_replace['FP_TOOLBAR']       = $toolbar;
	$all_replace['FP_FULL']          = $photo_path;
	$all_replace['FP_CAPTION']       = $row['caption'];
	$all_replace['FP_COLLECTION_ID'] = $row['collection_id'];
	
	// do the replacements (replace() shown a little farther down)
	$P->replace($display_photo_page, $all_replace);
	print $display_photo_page;
}

One last piece of code is the replace function. It transforms HTML templates into database-driven output:

/*
**    replace - do multiple replacements on $str, using $repl hash array
*/
function replace(&$str, $repl)
{
    while (list ($key, $val) = each($repl)) {
        $str = ereg_replace("$key", "$val", $str);
    }
    return $str;
}

Summary

In this article we have gone through the steps of separating program logic, HTML templates, and SQL statements. Our method hinges on a few key concepts:

  • Use separate files for PHP classes, HTML templates, and Resource Files, which include SQL (and other) information.
  • Employ heredocs to minimize ugly, heavily quoted, and backslashed assignment statements.
  • Adopt associative arrays as containers for variables coming from the user side, as well as read-only resources derived from them. This greatly simplifies function argument lists.

I have written a small example which illustrates this approach. The example additionally separates the calling PHP file (in an htdocs/ directory) from the PHP classes. I also show a method to switch between different HTML interfaces and different languages.

I hope this method helps you in your PHP scripting projects.

Daniel Smith is currently working on an Open Source web-based photography database in Apache/MySQL/PHP.


Return to the PHP DevCenter.


Valuable Online Certification Training

Online Certification for Your Career
Earn a Certificate for Professional Development from the University of Illinois Office of Continuing Education upon completion of each online certificate program.

PHP/SQL Programming Certificate — The PHP/SQL Programming Certificate series is comprised of four courses covering beginning to advanced PHP programming, beginning to advanced database programming using the SQL language, database theory, and integrated Web 2.0 programming using PHP and SQL on the Unix/Linux mySQL platform.

Enroll today!


Sponsored by: