Jump to content

Should I use a template engine?


NotionCommotion

Recommended Posts

Hello All!

 

Below is a simplified version how I render about every page.

Should I start using a dedicated template engine?  If so, which one and why?

Or, should I stick with my existing system?  If so, should I make any changes to it?

Thank you

<?php
class myModel {
    public function getData() //This would really be a query to a DB
    {
        $dataFromMyDB=new stdClass();
        $dataFromMyDB->firstname='John';
        $dataFromMyDB->lastname='Doe';
        $dataFromMyDB->age=111;
        return $dataFromMyDB;
    }
}
/**
* Typically used to htmlspecialchars variable.
* $nbsp=0: return htmlspecialchars input
* $nbsp=1: return htmlspecialchars input or &nbsp if nothing
* $nbsp=2: return input or &nbsp if nothing
* @param $html
* @param boolean $nbsp
*/
function h($html,$nbsp=0) {
    $html=trim($html);
    switch($nbsp)
    {
        //Consider changing ENT_QUOTES to ENT_QUOTES|ENT_XHTML or ENT_QUOTES|ENT_HTML401
        case 0:default:$return=htmlspecialchars($html, ENT_QUOTES, 'UTF-8');break;
        case 1:$return=($html)?htmlspecialchars($html, ENT_QUOTES, 'UTF-8'):' ';break;
        case 2:$return=($html)?$html:' ';break;
    }
    return $return;
}
function render($viewFile,$model)
{
    ob_start();
    require $viewFile;
    $html_string=ob_get_contents();
    ob_end_clean();
    return $html_string;
}

$model=new myModel();
echo(render('mvc_view.php',$model->getData()));
?>

mvc_view.php

<p>Hello!  This is my View</p>
<?php
    echo(h($model->firstname).' '.h($model->lastname).' is '.h($model->age).' years old.');
?>
Link to comment
Share on other sites

Hi NotionCommotion,

 

we've actually discussed this topic a week ago.

 

The thing is this: Yes, you can use PHP as a template engine, and that's indeed what is was originally designed for. But PHP is a template engine of the 90s. It may have been good enough in the early days of the Internet when amateurs wrote cute little home pages, but compared to the state of the art, it's hopelessly outdated. 

 

Modern template engines can do much more than just insert values into HTML markup. If you look at Twig, for example, you'll find a lot of useful features:

  • A proper syntax. After a while, you'll wonder why on earth you've spent your time writing down stupid PHP tags.
  • You can also define your own statements.
  • Values can be automatically escaped: Instead of cluttering your templates with htmlspecialchars() calls, you simply define an escaping strategy and let the template engine do the work.
  • Sandboxing makes sure that the templates indeed only render HTML documents and don't execute arbitrary PHP code.
  • Template inheritance lets you reuse templates and keep them simple (much like inheritance in OOP).

I think using Twig instead of plain PHP is similar using jQuery instead of plain JavaScript: Of course you don't need jQuery. An Ajax request can also be implemented in 100 lines of pure JavaScript code. But why would you do that? Programming is about getting things done, not writing down boilerplate code.

 

Regardless of that:

 

Or, should I stick with my existing system?  If so, should I make any changes to it?

 

Hard-coding the character encoding isn't really a good idea, and the magic numbers you pass to the second parameter are extremely confusing. That's what constants are for.

Link to comment
Share on other sites

I really don't like the idea of using a template engine. I had wrote out a lengthy explanation why, and then decided to shorten my response to simply "maintenance". PHP tags will always exist, but 3 years from now when X template engine is the hot new template engine, imagine the frustration when you need to update thousands of views to use X. 3 years after that X will be lame, and everyone using Y ....

 

The dev world is such that whatever plugin or awesome code you are using today, it will probably be outdated or obsolete in a few years. I'm not saying you need to use raw PHP, HTML, and JS for everything. I'm just saying that when you overdo it, you're going to pull your hair out in a couple years. This becomes way more important if you are working on scores of client websites. The decision is like that of choosing a PHP framework. 5 years ago you would have had many suggestions to use CodeIgniter, and today CodeIgniter is like the black sheep of frameworks.

 

So should you decide to use Twig, Handlebars, Smarty, or something else: http://www.webresourcesdepot.com/19-promising-php-template-engines/ ? I think your answer should indicate your willingness to deal with the possibility that it will not be desirable in the future.

Link to comment
Share on other sites

Thank you Jacques1 and sKunKbad,  You both bring up excellent, yet conflicting, points.  I guess I will need to ponder this for a bit.

 

 

 

Hard-coding the character encoding isn't really a good idea, and the magic numbers you pass to the second parameter are extremely confusing. That's what constants are for.

 

I understand your reasoning behind staying away from magic numbers and using constants instead.  Please elaberate on what you mean regarding not "Hard-coding the character encoding".
 
Link to comment
Share on other sites

Being afraid that the template engine might suddenly die doesn't make a lot of sense. Smarty has been around for 13 years, which is a lot given that PHP itself is less than 20 years old. It's also constantly updated and improved, and there's absolutely no reason to believe that this will change in the future. Twig is “only” 5 years old, but it's maintained by one of the most active and knowledgeable community in the PHP universe. This is not an amateur project like CodeIgniter.

 

But even if a template engine somehow dies, you can use a transcompiler to convert the templates into a different language. My company has actually done that just recently. We converted all templates of a big online shop from Smarty to Twig, and we had no issues whatsoever. We just had to do a few manual corrections for some edge cases. 

 

I'm actually surprised that template engines are still such a hot topic in the PHP community. And I'm baffled how many people insist on using the incredibly fugly, verbose and primitive PHP syntax. It's almost masochistic. ;)

 

 

 

Please elaberate on what you mean regarding not "Hard-coding the character encoding".

 

You've hard-coded the “UTF-8” setting into your function, but there are many other encodings you might encounter. This is not just a theoretical problem: If you or somebody else reuses the class for a different project which does not use UTF-8, the mismatch can in fact break the escaping mechanism entirely.

 

The encoding should be set by the user. For example, you could make a (mandatory) parameter in the constructor:

class View
{
	protected $encoding;

	public function __construct($encoding)
	{
		$this->encoding = $encoding;
	}

	// ...

	public function escape($data)
	{
		return htmlspecialchars($data, ENT_QUOTES, $this->encoding);
	}
}

If, for some strange reason, you insist on restricting the class to UTF-8-encoded templates, use a class constant and write a big warning into the script and the documentation:

class View
{
	const ENCODING = 'UTF-8';

	// ...

	public function escape($data)
	{
		return htmlspecialchars($data, ENT_QUOTES, self::ENCODING);
	}
}
Edited by Jacques1
Link to comment
Share on other sites

I'll admit there are some nice features to Twig, but I'm fully comfortable, fully capable, and very accustom to using PHP in my views. I think a dev has to look at modern template engines and make their own decision. Will it increase productivity? Maybe. Are there great benefits or detriments. Maybe. Asking others if a template engine is the right thing will lead to opinions, and that's what we have here. So OP just needs to dive in and check out some template engines, as well as considering opinions and determining what's right for him/her.

 

Maybe I need to switch gears. Maybe I could do X, Y, or Z. I've found out the hard way that things I was interested in were made obsolete, essentially wasting my time (and the money of my clients). So, I am just cautious when moving towards using a concept, library, plugin, framework, script, etc. I hear you when you say Smarty and Twig are not new, but there's something good about knowing how to code without them.

Link to comment
Share on other sites

Thanks Jacques1,

Yes, I knew you used Twig, but didn't know whether you just did the backend portion, and had someone else do the frontend template work.  Just curious, but do you use Syphony2 as well?

I've obviously looked at the Twig documentation, but I haven't found any tutorial describing typical application-wide design patterns.  My current thoughts (which might be wrong) are that I should make one general page template which includes the HTML, HEAD, BODY tags and other general content.  I would then extend this template to be more specific. I will pass an array listing external JS/CSS/etc resources to the template which would in turn insert them in the HEAD.  I am uncertain whether I will use PHP directly to create navigation menu and select option HTML and pass these to the template, or have the template create them from an array, or maybe there is some other approach altogether (thoughts?).  I could also use a second general template to render large HTML blocks requested from Ajax on the rare occasions that I don't want to just send back JSON.
I would appreciate any comments.  Also, if you know of a good article/book/blog/etc, please let me know.

Thanks

Link to comment
Share on other sites

Yes, I knew you used Twig, but didn't know whether you just did the backend portion, and had someone else do the frontend template work.

 

Passing some values to a template object on the backend hardly qualifies as “using Twig”, so I do mean the frontend. I create templates with Twig.

 

 

 

Just curious, but do you use Syphony2 as well?

 

No.

 

 

 

I've obviously looked at the Twig documentation, but I haven't found any tutorial describing typical application-wide design patterns.  My current thoughts (which might be wrong) are that I should make one general page template which includes the HTML, HEAD, BODY tags and other general content.  I would then extend this template to be more specific.

 

That's also what I do. However, the great thing about Twig is that there isn't really a “right” and a “wrong” way. You can choose from different techniques according to your personal preferences. For example, you don't have to use inheritance. You might as well make a template for the head section and insert that into each page template.

 

 

 

I will pass an array listing external JS/CSS/etc resources to the template which would in turn insert them in the HEAD.  I am uncertain whether I will use PHP directly to create navigation menu and select option HTML and pass these to the template, or have the template create them from an array, or maybe there is some other approach altogether (thoughts?).

 

You shouldn't have any HTML markup in your PHP code. I mean, preventing this kind of spaghetti code is pretty much the whole point of template engines.

 

The template should create the output, PHP only does the logic and provides the data. Think of the output as a completely separate aspect: Who says it's always HTML? Maybe one day you want a PDF document instead. Or an entirely different format. There's no reason why that shouldn't be possible given that the data isn't tied to HTML in any way.

Link to comment
Share on other sites

Thanks again Jacques1,

 

I see your point regarding HTML in the PHP script for a select menu, etc.  How do you handle this?  Previously, I would pass an array of options along with the selected value, and use a function to create a select menu.  Could I and should I do something similar with Twig?

 

Also, what about passing an array of JS/CSS/etc filenames from the controller to the Twig view?   While I don't see a way around it, it goes against keeping the controller totally isolated from presentation content.

Link to comment
Share on other sites

Thanks again Jacques1,Previously, I would pass an array of options along with the selected value, and use a function to create a select menu.  Could I and should I do something similar with Twig?

 

Personally, I would just create the menu ad hoc with a loop. But if you insist on hiding the details behind a single menu entity, you can use a macro.

 

Twig also supports functions, but those serve a very different purpose: They are executed within PHP and allow the template to pull data from the application. This is useful when the data is expensive in some way and at the same time not always needed. It would be a waste of resources to always push the data to the template, so instead you leave it to the template to pull the data when needed.

 

 

 

Also, what about passing an array of JS/CSS/etc filenames from the controller to the Twig view?   While I don't see a way around it, it goes against keeping the controller totally isolated from presentation content.

 

Why do the filenames need to come from the controller? The template should decide which files it needs. Each page template simply adds its own scripts or stylesheets to the head section of the basic template.

 

For example:

 

base.twig

<!DOCTYPE HTML>
<html>
    <head>
        {% block head %}
            <meta charset="utf-8">
            <title>{{ title }}</title>
            {% block style %}
                <link rel="stylesheet" href="{{ static_url('style/main.css') }}">
            {% endblock %}
            {% block scripts %}{% endblock %}
        {% endblock %}
    </head>
    <body>
        {% block body %}{% endblock %}
    </body>
</html>

blog.twig

{% extends "base.twig" %}

{% block style %}
    {{ parent() }}
    <link rel="stylesheet" href="{{ static_url('style/blog.css') }}">
{% endblock %}

{% block scripts %}
    {{ parent() }}
    <script src="{{ static_url('scripts/blog.js') }}"></script>
{% endblock %}

{% block body %}
    <h1>My blog</h1>
    <p>Welcome to my blog!</p>
{% endblock %}

Note that if you override a block, you can still get the original content with parent() function. So you can put standard stylesheets and scripts into your basic template.

Link to comment
Share on other sites

Personally, I would just create the menu ad hoc with a loop. But if you insist on hiding the details behind a single menu entity, you can use a macro.

 

No, I don't insist. Just adapting to a new way of looking at things.

 

Why do the filenames need to come from the controller? The template should decide which files it needs. Each page template simply adds its own scripts or stylesheets to the head section of the basic template.

 

In reflect, I agree they shouldn't come from the controller.  Again, I am looking at things differently, and it takes a bit of time it to sink in.

 

I am stronly leaning towards templates being a good thing unless you have a site with one million hits per hour in which you have no problems.

 

I posted a related post at http://forums.phpfreaks.com/topic/291199-recommended-application-structure/, and would appreciate any comments.

 

Thanks

Link to comment
Share on other sites

This thread is more than a year old. Please don't revive it unless you have something important to add.

Join the conversation

You can post now and register later. If you have an account, sign in now to post with your account.

Guest
Reply to this topic...

×   Pasted as rich text.   Restore formatting

  Only 75 emoji are allowed.

×   Your link has been automatically embedded.   Display as a link instead

×   Your previous content has been restored.   Clear editor

×   You cannot paste images directly. Upload or insert images from URL.

×
×
  • Create New...

Important Information

We have placed cookies on your device to help make this website better. You can adjust your cookie settings, otherwise we'll assume you're okay to continue.