views:

66

answers:

3

How can I improve the script below to be able to add global template parts such as start and end of the page?

  <?php
    class simpleTemplate {
        var $variables;
        var $variables_callback;
        var $contents;
        var $preg;
        var $regexps;
        // Constructor, initialize default variables
        function simpleTemplate(){
            // default sub regexp matches
            $this->preg['var'] = '[a-zA-Z.\-_]{1,50}';

            //INSERT REGEXP

            $this->php_start = "\necho '";
            $this->php_end = "';\n";
            // Main find-replace regexps
            $this->regexps = array(
                // echo-variable statement: {(var)}
                'echo' => array(
                    'search' => '~\{((?:'.$this->preg['var'].')(?:\.)?)\}~sU',
                    'replace' => "'.\$this->_get('\\1').'"
                )
       'include' => array(
           'search' => '', // UPDATE
                    'replace' => "" // UPDATE
       )
            );
        }
        // Load a file and convert it into native PHP code
        function load($file){
            if (!is_readable($file))
                return FALSE;
            $this->file = $file;
            $this->contents = NULL;
            if (!isset($this->contents)){
                $this->contents = file_get_contents($this->file);
                $this->parse();
            }
        }
        // Load a converted template, apply variables and echo the output
        function show(){
            ob_start();
            eval($this->contents);
            ob_end_flush();
        }
        // Main converter, call sub-convertors and perform some cleaning
        function parse(){
            $this->contents = str_replace("'", "\'", $this->contents);
            $this->contents = $this->php_start.$this->contents.$this->php_end;
            foreach ($this->regexps as $regexp)
                do {
                    if (isset($contents))
                        $this->contents = $contents;
                    $contents = preg_replace($regexp['search'], $regexp['replace'], $this->contents);
                } while ($contents != $this->contents);
            $this->clean();
        }
        // Clean trash in generated PHP code
        function clean(){
            $this->contents = preg_replace("~([^\\\])''\.~", '\1', $this->contents);
            $this->contents = str_replace(".''", "", $this->contents);
            $this->contents = str_replace("\necho '';\n", "", $this->contents);
            $this->contents = str_replace("else {}", "", $this->contents);
            // Remove all whitespace from the template output
            //$this->contents = preg_replace("~(\s{2,}|\n)~", '', $this->contents);
            return;
        }
        // Get a variable from internal, or an external source
        function _get($variableName){
            $variable = @eval('return $this->variables[\''.str_replace('.', "']['", $variableName).'\'];');
            if (!isset($variable)) {
                if (isset($this->variables[$variableName]))
                    $variable = $this->variables[$variableName];
                else {
                    // Support for an external variable-source
                    $function_name = $this->variables_function;
                    if (isset($variables_callback))
                        $variable = call_user_func($variables_callback, $variableName);
                }
            }
            if (!isset($variable))
                return FALSE;
            else
                return $variable;
        }
        // Set an internal variable
        function _set($variableName, $value){
            $this->variables[$variableName] = $value;
            return TRUE;
        }
    }
    ?>

Sample .php page looks like that

<?php
require_once('tpl.php');     
$tpl = new simpleTemplate();
$data['user'] = array(
        'name' => 'Denis',
        'surname' => 'Bobrovnikov'
);
$tpl->variables = $data;
$tpl->load('index.tpl');
$tpl->show();
?>

And the template is the following

My name is {user.name} {user.surname}

I want to be able to do so in the template file

{include=header.tpl}
My name is {user.name} {user.surname}
{include=footer.tpl}

where header and footer are also parsed

+1  A: 

1) use MVC pattern instead.
2) PHP is template engine. Why just dont use it?

codez
PHP is lousy template engine. Template engines in MVC are way to implement V and communication from M and C to V.
Kamil Szot
Models should not communicate with Views in MVC. And what does not let PHP controller to comunicate with PHP template?
codez
Yes but parts of models might be directly fed to view by controller. I'm not saying pure PHP can't do anything that templates can. I'm saying that pure PHP requires some very lousy syntax to implement some features templates have. Also I'm saying that MVC does not exclude use of templates because templates are just one possible implementation of V from MVC.
Kamil Szot
+1  A: 

Use an existing template engine if you want something on top of PHP, don't reinvent the wheel.
Give twig a go http://www.twig-project.org/

catchamonkey
A: 

It is my duty as a programmer to toot my own horn in the hope that I might be helpful.

Jon Purdy
Your project does not seem like template engine for PHP.
Kamil Szot
@Kamil: My project is a template language that can easily and effectively be used in conjunction with PHP, so what is the real difference?
Jon Purdy
Can't be used on many shared hosting services.
Kamil Szot