A buddy of mine read this post about PHP require performance and asked “why would you require a file multiple times?”.
That’s a fair question. There’s a zillion examples why you wouldn’t. Here’s a few obvious reason where you wouldn’t want to:
- using a
require 'header.php' & require 'footer.php' type “chrome” for the site
- using
require_once to ensure a class declaration is available
- load a file with a bunch of common functions
Anyways… there’s a bunch more why reasons to not require the same file more than once but there’s a “oh ya” reasons why you would. I’ll go through one simple case and one more complex case (which ill make even more complex in a following entry).
Zee simple case first:
Let’s say you’re working on a site that has 3 columns. The column’s satisfy the following roles:
- main content
- google ads
- inner site linking (not quite nav)
Topix pretty much has a 3 column layout like this. For the example’s sake let’s assume the middle column has 2 identically styled (colors etc) Google towers stacked one on top of the other. Here’s an awesome mockup of what I’m talking about:
When writing the code for this middle column you have a few choices:
- copy/paste the Google JS twice
- write a PHP function called something like
renderGoogleTower () and call that twice.
- create a file called google.html which would contain the JS and
require that file twice.
The third option above is a pretty legit reason to require the same file twice. Why not right? Copy and pasting the JS sucks (what if you wanted to change a color or 2? You’d have to duplicate code.). With the function call you’d have all this annoying escaping to do… so, the require option sounds like a decent solution.
Alright, let’s check out a more complicate example… a very basic templating system.
This time let’s say you’re working at Digg and you’ve gotta do the UI for this page. Again, you might be tempted to just write a function like renderArticle ($article, $currentUser = null) but when you’re working on a big ass site where the rendered stuff has JS and complex HTML you really don’t wanna do all the HTML in code. Also, its just a good idea to separate your business logic from your ui/display code. If you need more convincing read up on MVC and or Google it.
Now, ignore all the shit on the page like the nav and ads etc and concentrate on the middle of the page. All we’re gonna care about here is this part:
NOTE: i ditched a bunch of the links below each article to keep stuff simple.
The goal here is gonna be to be able to widgetize stuff so that we can render an article with just one function call no matter what page we’re displaying it on. In other words: we want a simple templating system that can give us a super easy way to display a PHP object.
The first thing we’re going to assume is that there’s an Article object that looks like this:
<?
class Article
{
public $title;
public $description;
// simplified
public $url;
public $domain;
// should be a tag object
// but assume a string to keep it easy
public $tag;
public function __construct ($title, $description,
$url, $domain, $tag)
{
$this->title = $title;
$this->description = $description;
$this->url = $url;
$this->domain = $domain;
$this->tag = $tag;
}
}
?>
The next thing we wanna do is sort out the HTML for a single article. That looks something like this lil diddy over here:
article-template.php
<?
// Assumes we have a PHP variable called $article
// $article is a Article object
// we’re ignoring htmlentities () to keep this short
?>
<div class=”article”>
<a class=”title” href=”<?= $article->url ?>“><?= $article->title ?></a>
<div class=”description”>
<span class=”domain”><?= $article->domain ?> —</span>
<?= $article->description ?>
<a class=”more” href=”<?= $article->url ?>“>More…</a>
<span class=”tag”>(<a href=”/<?= $article->tag ?>“ class=”tag”>
<?= $article->tag ?></a>)</span>
</div>
</div>
This gives us a nice and clean template for an Article. At this point we have 2 pieces of the puzzle. We’ve got an object we want to render and a clean PHP file that represents the object in HTML form. Sweet, now we’ve gotta connect the dots and come up with a way to get an Article to article-template.php. Here’s where we finally see another reason for require-ing the same file multiple times.
Since this is just an example we’ll take an easy approach and just write a quick function that can take an object and a template name and make the template render the object. That function could be as simple as:
<?
// $templatePath is a path to the template
// must be in your include_path
// $templateVars is an associative array
// all keys value pairs ($k => $v) in the array will turn into
// new variables in the scope of the template
// the variables’ name will be $k and the value will be $v
function renderTemplate ($templatePath, $templateVars = array ())
{
extract ($templateVars, EXTR_SKIP);
require ($templatePath);
}
?>
You might wanna look up the PHP docs for extract if you’re not familiar with it. Essentially it takes an associative array and creates a bunch of new variables; The names of the variables become the key from the array and the value of the new variable is the value for that key from the array.
So this little renderTemplate ($templatePath, $templateVars = array ()) function takes a path to a template (like article-template.php from above) and an associative array. It first extracts variables from $templateVars to create new variables in the function’s scope, then requires the template. Since a require is pretty much a copy/paste of the code then all the code in the template will have access to all the variables created by extract.
Finally lets make a quick runner script that puts all these pieces together and outputs the HTML generated by our lil tempating system. Everything (except the template) together, in one file, gives us:
<?
// The article class
class Article
{
public $title;
public $description;
// simplified
public $url;
public $domain;
// should be a tag object
// but assume a string to keep it easy
public $tag;
public function __construct ($title, $description,
$url, $domain, $tag)
{
$this->title = $title;
$this->description = $description;
$this->url = $url;
$this->domain = $domain;
$this->tag = $tag;
}
}
// our quick templating function
// $templatePath is a path to the template
// must be in your include_path
// $templateVars is an associative array
// all keys value pairs ($k => $v) in the array will turn into
// new variables in the scope of the template
// the variables? name will be $k and the value will be $v
function renderTemplate ($templatePath, $templateVars = array ())
{
extract ($templateVars, EXTR_SKIP);
require ($templatePath);
}
// Let’s make a couple quick Articles
$articles = array (
new Article (
‘Coolest Squirell EVER’,
‘Bla bla bla bla bla bla bla bla Bla
Bla bla bla bla bla bla bla bla
bla bla bla bla bla bla bla’,
‘http://www.nutsack.com’,
‘nutsack.com’,
‘Design’),
new Article (
‘My iPhone is better than yours’,
‘Some random bathering about an iPhone.
This guy is insane’,
‘http://someIdiotGuy.blogger.com’,
’someIdiotGuy.blogger.com’,
‘Apple’),
new Article (
‘Real Bigfoot caught on tape’,
‘A real video of Bigfoot taken in Washington state.’,
‘http://www.bfro.net’,
‘bfro.net’,
‘Videos’),
);
// quick setup bs
ini_set (‘include_path’, ‘.’);
// Finallly lets make them show up
// article-template.php is in the same folder as this file
foreach ($articles as $a)
{
renderTemplate (‘article-template.php’, array (‘article’ => $a));
}
?>
And there you have it. A overly simple templating “system” in PHP that gives us a valid reason to require the same file more than once. If you want to see it in action:
- click here to download the code
- extract the contents of the zip file to a temporary location in your web root
- finally, navigate to
article.php with your browser
Use the code for fucking around etc. It’s not awesome code so you shouldn’t use in your site… Some day soon I’ll do a writeup which will go through writing a full on templating system in PHP.