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; andFP_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.
-
:)
2004-05-28 05:15:07 3455TGTTRG [View]
-
dp independent interface?
2003-04-15 06:11:08 hmerrill [View]
-
dp independent interface?
2003-04-26 22:21:28 Daniel Smith | [View]
-
Why not use php-style instead of perlish ?
2003-04-12 06:42:57 anonymous2 [View]
-
Why not use php-style instead of perlish ?
2003-04-14 12:05:23 chromatic |
[View]
-
Why not use php-style instead of perlish (2)?
2003-04-12 06:55:56 anonymous2 [View]
-
Why not use php-style instead of perlish (2)?
2003-04-12 11:34:46 Daniel Smith | [View]
-
Why not use php-style instead of perlish (2)?
2003-04-15 03:32:34 anonymous2 [View]
-
Why not use php-style instead of perlish (2)?
2003-04-15 09:48:25 Daniel Smith | [View]