Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

PHP Simple Template Engine / Function

I'm required to create a simple template engine; I can't use Twig or Smarty, etc. because the designer on the project needs to be able to just copy/paste her HTML into the template with no configuration, muss/fuss, whatever. It's gotta be really easy.

So I created something that will allow her to do just that, by placing her content between {{ CONTENT }} {{ !CONTENT }} tags.

My only problem is that I want to make sure that if she uses multiple spaces in the tags - or NO spaces - it won't break; i.e. {{ CONTENT }} or {{CONTENT}}

What I have below accomplishes this, but I'm afraid it may be overkill. Anybody know a way to simplify this function?

function defineContent($tag, $string) {

    $offset = strlen($tag) + 6;

    // add a space to our tags if none exist
    $string = str_replace('{{'.$tag, '{{ '.$tag, $string);
    $string = str_replace($tag.'}}', $tag.' }}', $string);

    // strip consecutive spaces
    $string = preg_replace('/\s+/', ' ', $string);

    // now that extra spaces have been stripped, we're left with this
    // {{ CONTENT }} My content goes here {{ !CONTENT }}

    // remove the template tags
    $return = substr($string, strpos($string, '{{ '.$tag.' }}') + $offset);
    $return = substr($return, 0, strpos($return, '{{ !'.$tag.' }}'));

    return $return;
}

// here's the string
$string  = '{{     CONTENT  }} My content   goes here  {{ !CONTENT   }}';

// run it through the function
$content = defineContent('CONTENT', $string);

echo $content;

// gives us this...
My content goes here

EDIT

Ended up creating a repo, for anyone interested.

https://github.com/timgavin/tinyTemplate

like image 548
timgavin Avatar asked Aug 31 '25 18:08

timgavin


1 Answers

I would suggest to take a look at variable extraction into the template scope. It's a bit easier to maintain and less overhead, than the replace approach and its often easier to use for the designer. In its basic form, its just PHP variables and short tags.

It depends on which side you generate, e.g. a table and its rows (or complete content blocks) - it could be just <?=$table?> ;) Less work for the designer, more work for you. Or just provide a few rendering examples and helpers, because copy/pasting examples should always work, even with an untrained designer.

Template

The template is just HTML mixed with <?=$variable?> - uncluttered.

src/Templates/Article.php

<html>
 <body>
 <h1><?=$title?></h1>
 <div><?=$content?></div>
 </body>
</html>

Usage

src/Controller/Article.php

...

// initalize
$view = new View;

// assign
$view->data['title'] = 'The title';
$view->data['content'] = 'The body';

// render
$view->render(dirname(__DIR__) . '/Templates/Article.php');

View / TemplateRenderer

The core function here is render(). The template file is included and the variable extraction happens in a closure to avoid any variable clashes/scope problems.

src/View.php

class View
{
    /**
     * Set data from controller: $view->data['variable'] = 'value';
     * @var array
     */
    public $data = [];

    /**
     * @var sting Path to template file.
     */ 
    function render($template)
    {
        if (!is_file($template)) {
            throw new \RuntimeException('Template not found: ' . $template);
        }

        // define a closure with a scope for the variable extraction
        $result = function($file, array $data = array()) {
            ob_start();
            extract($data, EXTR_SKIP);
            try {
                include $file;
            } catch (\Exception $e) {
                ob_end_clean();
                throw $e;
            }
            return ob_get_clean();
        };

        // call the closure
        echo $result($template, $this->data);
    }
}
like image 92
Jens A. Koch Avatar answered Sep 02 '25 08:09

Jens A. Koch