MVC is all the rage. Choosing a framework, however, is not so easy. The You may not have realized that PHP is itself a templating engine. It allows you to intersperse logic and text, and has some handy features to make it easy. I’m going to show you how to build a php-based templating framework in one file. Please read Template Engines and Beyond Template Engine for background and other approaches to the same thing. They specifically address why you would want to use PHP instead of another layer for templating. post.php?id=2 templating/post_full.php templating/main_layout.php It’s simple to use, and requires nothing but basic php skills (maybe with the addition of knowing you can do that colon trick with loops). It’s simple, really. First let’s create the class, and add 3 fields. The main essential feature is that the engine include another php script and capture its output. You can easily do that with php’s output buffer functions. Let’s create a “run” function that will return the template’s content. Anything Next we need a way to store some variables so that Now that extract call will work as explained above. Finally, let’s add a You can get more fancy if you like. In the full example I added parents for templates, meaning they can access variables from their parent’s scope. I also added the
view part of a standard php MVC framework usually involves grabbing one or more model objects and printing out some text (html) about them. There are several frameworks that do this, including the famous smarty.There are even more frameworks, like Zend and CakePHP that include templating as a subset of what they do.The final product
<?php
require_once('SimpleTemplate.php');
$post = new BlogPost($_GET["id"]); // pretend we're fetching a post from a db
$main = new SimpleTemplate("templating/post_full.php");
$main->post = $post;
$main->comments = $post->comments;
$layout = new SimpleTemplate("templating/main_layout.php");
$layout->title = "Post - $post->title";
$layout->content = $main->run();
echo $layout;<h2><?= $post->title ?></h2>
<p><?= $post->body ?></p>
<hr>
<? foreach ($comments as $comment): ?>
<p>Comment - <?= "$comment->name - $comment-text" ?></p>
<? endforeach; ?>
<!-- Add a comment form here -->
<html>
<head>
<!-- some script tags, css, etc -->
<title><?= $title ?></title>
</head>
<body>
<h1>This is my site</h1>
<?= $content ?>
</body>
</html>How to make one?
source will store the variables, pathis the path to the template, and result contains the generated result.class SimpleTemplate
{
public $source;
public $path;
public $result;
}printed or echoed between ob_start() andob_get_contents() will be stored in $this->result.public function run()
{
ob_start();
extract ($this->source);
include $this->path;
$this->result = ob_get_contents();
ob_end_clean();
return $this->result;
}extract call works. extract takes the variables available in a certain scope and empties them into the current scope. So, we can set$template->title = "a title"; and that variable will be available in our template as $title. We’ll implement php’s magic __set() and __get() to do this.public function __set($name, $value)
{
$this->source[$name] = $value;
}
public function __get($name)
{
return isset($this->source[$name]) ? $this->source[$name] : "";
}__toString() method so we can just print $template; and use string concatenation and go nuts. Let’s also add a constructor that stores the $path variable.<?php
class SimpleTemplate
{
public $source;
public $path;
public $result;
public function SimpleTemplate($path=false)
{
$this->source = array();
$this->path($path);
}
public function __toString()
{
return $this->run();
}
public function __set($name, $value)
{
$this->source[$name] = $value;
}
public function __get($name)
{
return isset($this->source[$name]) ? $this->source[$name] : "";
}
public function run()
{
ob_start();
extract ($this->source);
include $this->path;
$this->result = ob_get_contents();
ob_end_clean();
return $this->result;
}
}extract method, which copies all the variables in an object into the scope (it saves a few characters).
This class and script makes it easy to turn a one-shot php script into a daemon that runs in the background on a timer. This is good for things you want to happen infrequently. For example, your site may need to use curl to fetch several different rss feeds, combining them into one feed. You don’t want to fetch all the feeds every time someone asks for the combined one. It is better to generate the combined feed every 5 minutes or so.
daemon generate_feed.php start daemon generate_feed.php stop daemon generate_feed.php restart
generate_feed.php might look like this
require_once("BlogDatabase.php");
echo "Generating Feed"; // this will go to the log
$data = new BlogDatabase();
$posts = $data->getAllNewPosts();
foreach($posts as $post)
{
// generate an rss feed
}
file_put_contents("feed.xml", $contents);Alternatives
-
crontab - This is the easiest way to get a script to run on a timer, but there are a few disadvantages. Specifically, you don’t have exact control over the timer, nor can you prevent the script from running if the system isn’t ready. Refer to this article for more information.
-
System_Daemon - This was built using
System_Daemon. I created this because my daemons were behaving strangely. Our database calls weren’t working properly, and things were just generally messed up.
What it does
This uses the pear System_Daemon to create a daemon that runs your script every 5 seconds (by default). It uses shell_exec to run it, giving you the following advantages.
-
Your script runs in a “sandboxed” environment. You don’t have to worry about stale variables or strange processes making your code behave strangely.
-
You can test your script by running it on the command-line, since this is exactly what the daemon does.
-
You can easily start and stop the daemon using the included tool.
-
It puts output from the script into the daemon’s log (
/var/log/generate_feed.logon my system)
Sorry it isn’t more flexible right now, but the timer can be easily changed in Daemon.php
Installation
You need to install the pear System_Daemon module. Refer to this article for instructions.
Put your daemons in the same folder as these scripts, or else make sure Daemon.php is in your include path when you run daemon from the command line.
