Jordyn Jordyn - 15 days ago 9
PHP Question

Simple PHP template class

I wanted separate my HTML from PHP so after searching I found a great little php class that just do the trick. Only issue that I try merging 2 templates together but it doesn’t work.

Here is the original class that i found from below website

http://www.broculos.net/2008/03/how-to-make-simple-html-template-engine.html#.WCsa8CTy2ng

class Template {
/**
* The filename of the template to load.
*
* @access protected
* @var string
*/
protected $file;

/**
* An array of values for replacing each tag on the template (the key for each value is its corresponding tag).
*
* @access protected
* @var array
*/
protected $values = array();

/**
* Creates a new Template object and sets its associated file.
*
* @param string $file the filename of the template to load
*/
public function __construct($file) {
$this->file = $file;
}

/**
* Sets a value for replacing a specific tag.
*
* @param string $key the name of the tag to replace
* @param string $value the value to replace
*/
public function set($key, $value) {
$this->values[$key] = $value;
}

/**
* Outputs the content of the template, replacing the keys for its respective values.
*
* @return string
*/
public function output() {
/**
* Tries to verify if the file exists.
* If it doesn't return with an error message.
* Anything else loads the file contents and loops through the array replacing every key for its value.
*/
if (!file_exists($this->file)) {
return "Error loading template file ($this->file).<br />";
}
$output = file_get_contents($this->file);

foreach ($this->values as $key => $value) {
$tagToReplace = "[@$key]";
$output = str_replace($tagToReplace, $value, $output);
}

return $output;
}

/**
* Merges the content from an array of templates and separates it with $separator.
*
* @param array $templates an array of Template objects to merge
* @param string $separator the string that is used between each Template object
* @return string
*/
static public function merge($templates, $separator = "\n") {
/**
* Loops through the array concatenating the outputs from each template, separating with $separator.
* If a type different from Template is found we provide an error message.
*/
$output = "";

foreach ($templates as $template) {
$content = (get_class($template) !== "Template")
? "Error, incorrect type - expected Template."
: $template->output();
$output .= $content . $separator;
}

return $output;
}
}


Code that work

$post = new Template("post.tpl");
$post->set("post_title", $post_title);
$post->set("post_description", $post_description);
$post->set("content", $post->output());
echo $post->output();


Even when I want to loop if I add the code it works fine. But then I try to merge two template files together

all_posts.tpl

<div class=”posts”>
<h1>[@page_title]</</h1>
[@display_posts]
</div>
display_posts.tpl
<div class=”post”>

<h2>[@display_title]</h2>

<p>[@display_description]</p>

</div>


So what I want to do now is to push display_posts.tpl to all_posts.tpl and replace the tag [@display_posts]

So in my php I did below

$post = new Template("all_posts.tpl ");
$post->set("page_title", "All Posts");
echo $post->output();

//created a array from a mysqli loop

$post_set = array();

while ($post_row = mysqli_fetch_array($posts)){

$post_title = $post_row['title'];
$post_description = $post_row['description'];

$post_set[] = array(
"display_title" => $post_title,
"display_description" => $post_description
);

}



foreach ($post_set as $posts) {
$row = new Template("list_users_row.tpl");

foreach ($posts as $key => $value) {
$row->set($key, $value);
}
$postsTemplates[] = $posts;
}

// here i try to merge template

$postsContents = Template::merge($postsTemplates);

$layout->set("content", $postsContents->output());

echo $layout->output();


But this is throwing off a error set() is not an function. Could someone help me out to figure out this? I’m still in the process of learning php classes.

Answer

The reason why $layout->set() does not work is because $layout is not a Template Object. In your code you use $post = new Template("all_posts.tpl ");. This makes $post a Template object that can use the set() function in your Template class.

So you should do: $layout = new Template(....) and than you can call $layout->set().

In the tutorial they do the same:

include("template.class.php");
$profile = new Template("user_profile.tpl");
$profile->set("username", "monk3y");
$profile->set("photoURL", "photo.jpg");
$profile->set("name", "Monkey man");
$profile->set("age", "23");
$profile->set("location", "Portugal");

$layout = new Template("layout.tpl");
$layout->set("title", "User profile");
$layout->set("content", $profile->output());

echo $layout->output();

Hope this helps.