0

I'm trying to write a very basic template engine for a project and ended up taking the approach described in this article, which write template variables like [@variable] and to simply use str_replace() to parse the templates and put in the variable values.

This is really simply and seems to work well, but despite my best efforts there are situations in which basic logic is really needed in the template itself. I don't need anything complicated, just a way to have single if/else or ternary statements. For example, something like [if@something?"text":"other text"].

What might be a good approach to parsing basic logic in templates, like shown in the above example?

UPDATE:

I'm working on an AJAX heavy website, so I have a PHP AJAX controller that receives requests and then returns a JSON encoded response. Here's an example:

AJAX handler.php:

...
else if($req == 'getContent')
{
    $template = new Template('template.tpl');
    $template->setData(array(
        'date' => time(),
        'var'  => 'foo',
        'foo'  => 'bar'
    ));

    $response = array(
        'error' => null,
        'content' => template->getOutput()
    );
}
...

echo json_encode($response);

template.tpl:

lots and lots and lots of HTML
........
variables [@date] mixed in [@foo] somewhere with HTML [@bar]
........
lots and lots and lots of HTML

If I wasn't using a template engine (which just uses str_replace() to put the variable values into the template after getting it with file_get_contents()), then I would have to do this:

AJAX handler.php:

...
else if($req == 'getContent')
{

    $output = '
        lots and lots and lots of HTML' . time() . '
        ........
        variables ' . $foo . ' mixed in ' . $bar . 'somewhere with HTML
        ........
        lots and lots and lots of HTML
    ';

    $response = array(
        'error' => null,
        'content' => $output
    );
}
...

echo json_encode($response);

The whole point of what I'm trying to accomplish here is to separate huge blocks of HTML text (in some cases, literally entire page bodies) from my AJAX handler and instead keep them in separate files, which is far more readable and keeps the AJAX handler from becoming ridiculously massive.

Nate
  • 26,164
  • 34
  • 130
  • 214
  • 1
    PHP already is a template engine - why not use that? ` echo (something ? "text" : "other text") ?>` What's the point in replicating that functionality? – Pekka Jan 12 '14 at 23:31
  • 1
    Use regex to match the statements and process accordingly. – RageD Jan 12 '14 at 23:35
  • @Pekka웃 The reason is to avoid mixing HTML with PHP and having spaghetti code: http://en.wikipedia.org/wiki/Spaghetti_code. Maybe there's a way to stick with PHP and avoid spaghetti code, though? – Nate Jan 12 '14 at 23:50
  • @Pekka웃 Using a template, like in the article I linked to, there isn't spaghetti code in the template itself, which makes the HTML much more readable. What I'm trying to do is separate my PHP code from my HTML code (mostly, as I've found that some basic if/else statements are really necessary). – Nate Jan 13 '14 at 00:20
  • @Nate can you tell me what the difference between ` echo (something ? "text" : "other text") ?>` and `[if@something?"text":"other text"]` is? (Except that the latter won't be compatible with any syntax highlighter, among other things.) How is the one "Spaghetti code" and the other isn't? – Pekka Jan 13 '14 at 00:25

2 Answers2

1

PHP is already a templating language. For example, this is what your example above would look like in PHP:

<? echo (something ? "text" : "other text") ?>

Think twice before adding another layer of complexity on top of this.

There are templating libraries like Smarty and they have their justification, for example caching, or when you want to separate code and design in a safe way (i.e. give designers something they can modify without breaking code). If it's just for your own use, though, then using native PHP is a very strong option.

The reason is to avoid mixing HTML with PHP and having spaghetti code

There is nothing wrong with using simple PHP inside your HTML code. (and whether you have spaghetti code in PHP or your new templating language doesn't really make a difference....)

What's bad (and leading to Spaghetti code) is mixing huge chunks of code with the HTML output, for example calculations or preparations. Those should always be separate from the HTML.

The PHP inside the HTML structure should do only simple comparisons, if/then/else checks, for/foreach loops, and any operations directly related to outputting data (e.g. htmlspecialchars or simple calculations).

If you stick to that, you can happily use native PHP for your templating needs.

Community
  • 1
  • 1
Pekka
  • 442,112
  • 142
  • 972
  • 1,088
  • The project I'm working on now is AJAX heavy. I need to make AJAX requests to a PHP handler and then return large blocks of HTML. Using a basic template engine like I linked to in my question, I can have a plain HTML file with some template variables in it and return the template engine output as my AJAX response. If I didn't use a template, I would have to have all of that HTML in one giant block (concatenated together with PHP variables) in my AJAX handler, right? – Nate Jan 13 '14 at 00:26
  • @Nate Not really. You can have PHP templates and `include()` them, in the same way as you would have a template file. Whether the file's extension is .html or .php doesn't really matter, as both won't be valid HTML anyway before you process them. You can do with native PHP exactly what you can do with a template engine, except that you won't need a super complicated library on top of PHP to do it – Pekka Jan 13 '14 at 00:26
  • Wouldn't code inside of the `include`d file have to be pure PHP (i.e. all the HTML in a string variable, being inside quotes, having all of it's quotes escaped, etc.)? Also, I need the template output in a variable, which can be put into an array with other variables, `json_encode`d, and `echo`d out as the AJAX response. Maybe there's a way to get the output of a PHP file as a string and I'm just not aware of it? As an example, the current basic template engine I'm using gets the template with `file_get_contents` and then uses `str_replace` to put in the template variable values. – Nate Jan 13 '14 at 00:36
  • @Nate maybe that's the misunderstanding then. You can take any HTML file, rename it to .php (or not - doesn't matter, but it's safer), add a couple tags ` echo json_encode(...); ?>` in the right places, and `include()` that. The HTML will be passed through no problem. Your template can contain *only* HTML if you want, and it'll be passed through – Pekka Jan 13 '14 at 00:40
  • The problem is that all of the template output needs to be json_encoded, so I can't put ` echo json_encode(...); ?>` into the template and then just `include` the template. I've been searching since you posted your answer and found out about output buffering, and that looks like it might work, though.. – Nate Jan 13 '14 at 00:51
  • @Nate hmm, if you're building a JSON structure, maybe you should build that structure inside the PHP code anyway? As in, `if (xyz) $structure->property = 500; else ....` Maybe the template approach isn't perfectly appropriate here (but then I don't know your project so I can't say) – Pekka Jan 13 '14 at 00:53
  • I updated my question since I don't think what I'm trying to accomplish was clearly stated. Thanks for all of your advice. – Nate Jan 13 '14 at 01:13
  • @Nate you're welcome. Ahh, makes sense now. This *can* be done in native PHP with output buffering and `include()`, but I can kinda see the point in using a templating language for this. – Pekka Jan 13 '14 at 01:16
  • Thanks. Do you think using output buffering is the best approach for what I need to do (from the example I gave)? – Nate Jan 13 '14 at 01:36
  • @Nate it's a viable and simple option, yes. The only reason I can think of to seriously consider building a templating engine of your own (or using an existing one like Smarty) would be security/ease of use for non-technical people (if those would ever need to edit that template). In that case, you may *want* the additional layer so nothing broken/malicious can influence the entire PHP script. Other than that, PHP is fine. – Pekka Jan 13 '14 at 01:52
0

Maybe you can define another template definition for functions, like:

[*function_name][param1,param2,param3]

For example for your example:

[*defined][@something,"text","other"]

And in your template engine code you can write the logic for the "defined" template function.

Just an idea!!