Framework PHP Tutorial August 03, 2009

How to write your own PHP templating engine

MVC is all the rage. Choosing a framework, however, is not so easy. 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.

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.

The final product

SimpleTemplate.php

post.php?id=2

<?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;

templating/post_full.php

<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 -->

templating/main_layout.php

<html>
<head>
    <!-- some script tags, css, etc -->
    <title><?= $title ?></title>
</head>
<body>
    <h1>This is my site</h1>
    <?= $content ?>
</body>
</html>

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).

How to make one?

It’s simple, really. First let’s create the class, and add 3 fields. source will store the variables, path is the path to the template, and result contains the generated result.

class SimpleTemplate
{
    public $source;
    public $path;
    public $result;
}

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 printed or echoed between ob_start() and ob_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;
}

Next we need a way to store some variables so that 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] : "";
}

Now that extract call will work as explained above. Finally, let’s add a __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;
    }
}

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 extract method, which copies all the variables in an object into the scope (it saves a few characters).



Thanks a lot! This helped me develop the view component for a MVC framework I'm working on.

sdgfhfnhmghfhdtrsfad





Wow


Wow

RE: How to write your own PHP templating engine
I am happy to find so many useful information here in the post, thanks for sharing.

Thanks. This class is very nice, though I would like this article to explain more thorough how the data is passed around. I made it to work, but I don't understand the logic.

very nice and informative, thansk a million cheers

Great Blog! Will visit again

Thank you for the information, keep up the good work

Excellent post, thanks.

Just the information I was looking for, thank you

Very interesting, will visit again

Great posting but better kick out those spammers comments as they are making your blog much worst...

I have been to your blog before and there are some awesome posts that i can find. I have actually forwarded this post to many of my friends as this would be great for discussion in our school!

I read your article.The things you have written sound very sincere and nice topics i am looking forward to its continuation. Rip blu ray|Many of us don't know about this event. Your post is helpful in this case

I am pretty much happy to visit your blog and enjoy it. Me and my family will be so much helpful to create all the possibilities for me to enjoy the following text. Hope I could find more sites to visit.

Concept Creations was established in year 2002 with the aim of manufacturing and maintaining best quality and unique designs in the field of Home Furnishings, Antique Furniture and Colonial Furniture.

I am a programmer and these informations is great and you explain very great .

This is the embroidered shirt for parties, beach weddings etc. It will look great with any pair of trouser. It is made from 100 % cotton fabric.

Your comment was added successfully
Your comment could not be added

Leave a comment