tags:

views:

67

answers:

5

I'm trying to create a small template system and have a function that loops over an array of items. Currently I'm using the output buffering functions and include so i can load up the template file while it has scope to the class.

function loadTemplate($name, $vars) {
    $buf = '';
    $path = $name . '.html';
    if (file_exists($path)) {
        $this->vars = $vars;
        ob_start();
        include($path);
        $buf = ob_get_clean();
    }
    return $buf;
}

I was just wondering if I could store the initial template in an array then have it run (As if it was included) while keeping scope, like.

function loadTemplate($name, $vars) {
    $buf = $template = '';
    if (isset($this->cache[$name]))
        $template = $this->cache[$name];
    else {
        $path = $name . '.html';
        $template = file_get_contents($path);
        $this->cache[$name] = $template;
    }
    //Exec template here with scope.
}

Or am i just being pedantic and trying to micro optimize :)

A: 

Hi,

I don't think that it makes much difference if you include an template once again, as you said yourself... it would be micro optimizing. But, what you could do is to save the already included templates source to an array and use the template name as the key for the array. When you run your loadTemplate function, you can just do a array_key_exists to see if it is included already.

But if I may, I would recommend the smarty template engine (http://www.smarty.net). I used it in my projects and find it just perfect. I have adapted it a bit to run smoother with my code, but now it really is perfect for me.

Regards,
Paul Peelen

Paul Peelen
A: 

Just keep including it. The only alternative would be to read the contents then eval them, and that's going to be worse. The overhead of the second include should be significantly less since the page is already parsed into opcode...

ircmaxell
"the page is already parsed into bytecode" What???
NullUserException
Sorry, I mean't to say opcode...
ircmaxell
+1  A: 

If i were you and had complex operations in the template files I would save them to filesystem. I've modified your function, I think you'll understand what happens there:

<?php

function template($name, $vars = array())
{
    $cache = 'cache/'; // Path to cache folder, must be writeable
    $expire = 3600 * 3; // Cache lifetime, 3 hours
    $path = $name . '.html';
    $cache_file = $cache . sha1($path) . '.txt'; // Generate cache file path and hash-name

    // If cache file exists and it hasn't expired yet we must get cached data
    if (file_exists($cache_file) && filemtime($cache_file) > (time() - $expire))
    {
        return unserialize(file_get_contents($cache_file));
    }

    // Return NULL if template file doesn't exist
    if (!file_exists($path))
    {
        return null;
    }

    $this->vars = $vars;

    ob_start();
    include_once $path;
    $output = ob_get_clean();

    // Save output to the cache file
    file_put_contents($cache_file, serialize($output));

    return $output;
}

?>

P.S. Haven't tested the function.

Otar
My main thought was to try and reduce the amount of disk reading but i think it would just over complicate for little performance gains.
Alex
I'm not sure that this will do what's necessary... The issue is that (from what I'm gathering) the output of the file will change dependent upon `$vars`. So you'd at least need to adjust your cache file definition to be dependent upon that array. Which will likely kill your cache hit rate if anything changes temporally (or at least result in a ton of cache files for each "template" file)...
ircmaxell
A: 

That's most useless cache you can implement. You'd better think of HTTP conditional get implementation which will make no need to call temlpate at all. And then go for opcode cache which will cache your includes automatically.

But at firs you have to profile your app/templater to see if you need any cache at all

Col. Shrapnel
A: 

Will be looking into CakePHP as per NullUserException's comment :)

Alex