One thing I see is that in your address_sql method, you dynamically open the $variable_name file; however, you statically load it's size....
// Open "rows.addresses" file and read contents into variable.
$fh = fopen("$variable_name", "r");
$file_contents = fread($fh, filesize("news_body.tpl") );
Now your real issue is between your address_sql method and the file_parser method. If you follow your logic in your code, you store the variable name "news_body.tpl" into the variables array (which is good). Just before that, you save the $complete_table to the SQL array with the key being the variable name. Then later in your parse_file method, you don't see whether there's a SQL array value for it, you just automatically decide that the variable name is already declared somewhere. So when $news_body.tpl comes up as a variable that (1) Isn't allowed to be a variable since a "." is in the name [see Variables] and (2) it isn't declared anywhere.
So to fix your problem I have a couple suggestions. It's your choice which you go with:
1.) Check for the variable in the SQL array first, then default to a string
[indent]Using this method you'd first run a quick if(array_key_exists()) on the $this->sql array to see if the variable name requested is in the array. If it is, then use that value, otherwise, try and globally get the string:[/i]
// Inside of parse_file method:
while ($x < sizeof($this->variables[$file_id])) :
// retrieve the next variable
$string = $this->variables[$file_id][$x];
if(array_key_exists($string, $this->sql))
{
$value = $this->sql[$string];
}
else
{
// retrieve this variable value! Notice that I'm using a
// variable variable to retrieve this value. This value
// of the corresponding variable
// name.
GLOBAL $$string;
$value = $$string;
}
// What exactly is to be replaced in the file contents?
$needle = $this->opening_escape.$string.$this->closing_escape;
// Perform the string replacement.
$this->files[$file_id] = str_replace(
$needle, // needle
$value, // string
$this->files[$file_id]); // haystack
// Your method then continues....
[/indent]
2.) Use one large array with the keys being the variable names, and the values being what will replace the variables:
[indent]Using this method, your $this->variables[$file_id] array would turn into something like: $this->variables[$file_id][$variable_name] = $variable_value; which then would be iterated over and each variable replaced into the template. Here's a small example:
<?php
class template {
VAR $files = array();
VAR $variables = array();
VAR $opening_escape = '{';
VAR $closing_escape = '}';
VAR $address_table = 'news';
// Function: register_file()
// Purpose: Store contents of file specified by $file_id
function register_file($file_id, $file_name) {
// Open $file_name for reading, or exit and print an error message.
$fh = fopen($file_name, "r") or die("Couldn't open $file_name!");
// Read in the entire contents of $file_name.
$file_contents = fread($fh, filesize($file_name));
// Assign these contents to a position in the array.
// This position is denoted by the key $file_id
$this->files[$file_id] = $file_contents;
// We're finished with the file, so close it.
fclose($fh);
} // end register_file;
// Function: register_variables()
// Purpose: Store variables passed in, via $variable_name under the corresponding
// array key, specified by $file_id
function register_variables($file_id, $variable_name) {
$input_variables = explode(",", $variable_name);
while (list(,$value) = each($input_variables)) :
$this->variables[$file_id][$value] = '';
endwhile;
} // end register_variables
// Function: file_parser()
// Purpose: Parse all registered variables in file contents
// specified by input parameter $file_id
function file_parser($file_id) {
$varcount = count($this->variables[$file_id]);
$keys = array_keys($this->files);
// If the $file_id exists in the $this->files array and it
// has some registered variablesā¦
if ( (in_array($file_id, $keys)) && ($varcount > 0) ) :
$x = 0;
// Loop through every variable for that $file_id
foreach($this->variables[$file_id] as $var => $val):
// Create the variable to search for:
$needle = $this->opening_escae.$var.$this->closing_escape;
// Replace the variable in the template with the value:
$this->files[$file_id] = str_replace($needle, $val, $this->files[$file_id]);
endforeach;
endif;
} // end file_parser
// Function: print_file()
// Purpose: Print out the file contents specified by input parameter $file_Id
function print_file($file_id) {
print $this->files[$file_id];
}
// Function address_sql()
function address_sql($file_id, $variable_name) {
require_once('config.php');
$query = "SELECT text FROM $this->address_table";
$result = mysql_query($query);
// Open "rows.addresses" file and read contents into variable.
$fh = fopen("$variable_name", "r");
$file_contents = fread($fh, filesize("news_body.tpl") );
// Perform replacements of delimited variable names with table data
while ($row = mysql_fetch_array($result)) :
$new_row = $file_contents;
$new_row = str_replace(
$this->opening_escape."text".$this->closing_escape,
$row["text"],
$new_row);
// Append new table row onto complete substitution string
$complete_table .= $new_row;
endwhile;
// Assign table substitution string to SQL array key
$this->variables[$file_id][$variable_name]=$complete_table;
fclose($fh);
} // end address_sql
}
?>
[/indent]
Hope that helps you out. The second option makes things much easier for you, especially if you decide to start using multiple templates or adding another "source" for data.
I'd also like to point out that I don't think "GLOBAL $$string;" would work since you're trying to globalize a variable that is created inside a function. I think GLOBAL only works to go from the file-scope to the function-scope, not one function-scope to another function-scope like what you're trying to do here. So just another reason to use the second option.