Welcome to WebmasterWorld Guest from 50.17.5.36

Forum Moderators: coopster & jatar k

Message Too Old, No Replies

The One Line Template Engine!

Just for fun...

     
7:03 am on Sep 8, 2007 (gmt 0)

Senior Member from MY 

WebmasterWorld Senior Member vincevincevince is a WebmasterWorld Top Contributor of All Time 10+ Year Member

joined:Apr 1, 2003
posts:4847
votes: 0


The engine itself:
print preg_replace("/\{([^\{]{1,100}?)\}/e","$$1",file_get_contents("template.tpl"));

Format of template.tpl file:

<html>
<head>
<title>{title}</title>
</head>
<body>
<h1>{header}</h1>
{text}
</body>
</html>

Setting variables:

$title="Example page";
$header="My Examples";
$text="See the placeholders replaced?";

If you're not comfortable with pulling variables out of the global scope, define them as

$values['title']="..";
etc., and use:
print preg_replace("/\{([^\{]{1,100}?)\}/e","$values[$1]",file_get_contents("template.tpl"));
4:21 pm on Sept 10, 2007 (gmt 0)

Administrator

WebmasterWorld Administrator coopster is a WebmasterWorld Top Contributor of All Time 10+ Year Member

joined:July 31, 2003
posts:12533
votes: 0


Can you explain your regular expression logic for us? For example, why search for anything that is not another opening brace? And make it optional? A nice, simple little example here, by the way.
3:31 am on Sept 11, 2007 (gmt 0)

Senior Member from MY 

WebmasterWorld Senior Member vincevincevince is a WebmasterWorld Top Contributor of All Time 10+ Year Member

joined:Apr 1, 2003
posts:4847
votes: 0


"/\{([^\{]{1,100}?)\}/e","$$1"

I'm delimiting the regular expression with / / and using the modifier 'e' which causes the second argument to be evaluated by PHP.

The pattern looks for an opening curly-brace ( \{ ) - the end of the pattern is a closing curly-brace ( \} ).

In between the two braces I look for any character which isn't an opening curly-brace [^\{], avoiding mistaken nesting of tags.

I match between 1 and 100 of these non-{ characters by writing {1,100} and then I make the match non-greedy (try to find the shortest strings between { and }, not the longest) by adding a?. (? after *, + or {a,b} expressions changes them to non-greedy - in other situations? means 0 or 1 of the preceding).

The full string of non-{ characters is matched and stored as string $1 by surrounding that part of the pattern with brackets ().

Finally, the second argument of the preg_replace is "$$1", using variable variables. If the pattern encounters "{title}" then the matched string $1 is "title" and so $$1 is $title.

3:39 pm on Sept 11, 2007 (gmt 0)

Administrator

WebmasterWorld Administrator coopster is a WebmasterWorld Top Contributor of All Time 10+ Year Member

joined:July 31, 2003
posts:12533
votes: 0


Nice. Thanks for the explanation as it will be beneficial to future readers.
4:00 pm on Sept 11, 2007 (gmt 0)

Preferred Member

10+ Year Member

joined:June 20, 2003
posts:558
votes: 0


That's really slick
5:35 pm on Sept 11, 2007 (gmt 0)

Senior Member

WebmasterWorld Senior Member whoisgregg is a WebmasterWorld Top Contributor of All Time 10+ Year Member

joined:Dec 9, 2003
posts:3416
votes: 0


Niiice. I especially appreciate the explanation of the regular expression. :)
7:44 pm on Sept 11, 2007 (gmt 0)

Senior Member

WebmasterWorld Senior Member dreamcatcher is a WebmasterWorld Top Contributor of All Time 10+ Year Member

joined:Mar 30, 2003
posts:3719
votes: 0


what about using str_replace?

echo str_replace(array('{header}','{title}','{body}'),array('header','title','body'),file_get_contents("template.tpl"));

dc

7:48 pm on Sept 11, 2007 (gmt 0)

Senior Member

WebmasterWorld Senior Member 10+ Year Member

joined:Apr 3, 2003
posts:1633
votes: 0


> why not use str_replace

Using regexp's makes it generic, so {anything} will be replaced with $anything etc..

7:49 pm on Sept 11, 2007 (gmt 0)

Senior Member

WebmasterWorld Senior Member 10+ Year Member

joined:June 13, 2002
posts:662
votes: 0


Depends which is faster.

Multiple string replaces (more than three) tend to be faster done with preg_replace, fewer replaces are quicker with str_replace.

Or so the benchmarks I recall seemed to indicate.

So it all depends how many things you plan to have in your template.

EDIT:
And yes, looking back, I notice the "generic" factor is huge.

[edited by: Gibble at 7:50 pm (utc) on Sep. 11, 2007]

11:07 am on Sept 12, 2007 (gmt 0)

Senior Member from MY 

WebmasterWorld Senior Member vincevincevince is a WebmasterWorld Top Contributor of All Time 10+ Year Member

joined:Apr 1, 2003
posts:4847
votes: 0


> why not use str_replace

Exactly as dmorison said - to make it generic. It's not normally expected that you have to list the tags which you're going to use. Although, if all fields are defined within an array such as $values['{title}'], $values['{header}'], etc. then you could use array_keys($values) and $values as the arguments to your str_replace making it more generic.

The str_replace would probably be faster for some cases, although it would depend upon the number of tags to be replaced. On the positive side for the str_replace, it would be more secure if you didn't have control over your .tpl file.

One difference in end result is that with the preg_replace method, a tag enclosed in {} but not matched by a variable will be removed ("Hello {name}!" => "Hello!"), whereas the str_replace method would leave that unreplaced tag in place ("Hello {name}!" => "Hello {name}!")

12:41 pm on Sept 12, 2007 (gmt 0)

Senior Member

WebmasterWorld Senior Member dreamcatcher is a WebmasterWorld Top Contributor of All Time 10+ Year Member

joined:Mar 30, 2003
posts:3719
votes: 0


Thanks guys, just thought str_replace was worth mentioning as other people might have been thinking it. I`ve actually been using the str_replace method on some of my own dev stuff for a while now, but as you mentioned, ideal for only a few tags.

dc

5:42 pm on Sept 12, 2007 (gmt 0)

Junior Member

5+ Year Member

joined:Feb 4, 2007
posts:73
votes: 0


This is very cool... thanks for the thread.. been wondering how to accomplish this for some time now...

Didn't understand all the Regular expression explanation, but I will in time...

Thanks again...

12:03 am on Sept 13, 2007 (gmt 0)

Full Member

10+ Year Member

joined:June 24, 2005
posts:267
votes: 0


Is it possible to use include (ie include a dynamic PHP page) in place a variable? In this case maybe "text"?

EDIT: Figured it out.

function get_include_contents($filename) {
if (is_file($filename)) {
ob_start();
include $filename;
$contents = ob_get_contents();
ob_end_clean();
return $contents;
}
return false;
}
$text = get_include_contents(somefile.php);
1:09 am on Sept 13, 2007 (gmt 0)

Senior Member from MY 

WebmasterWorld Senior Member vincevincevince is a WebmasterWorld Top Contributor of All Time 10+ Year Member

joined:Apr 1, 2003
posts:4847
votes: 0


mooger35, you can do that - or there are two other options:

1) Inside 'somefile.php', everywhere you see 'print' or 'echo' change it to '$text.=' - this will mean you can just do include('somefile.php'); and $text will be filled with the output:

print "Good morning $name"; ==> $text.= "Good morning $name";

2) Use a http:// request to file_get_contents(). $text=file_get_contents("http://your.example.com/somefile.php"); - this runs it as a separate Apache instance and you get the full results to variable

Your solution is fine, apart from it being a whole extra function to define. Be careful though as your variable scope is still shared, e.g. if you set $a=7 in somefile.php, $a still equals 7 afterwards.

8:24 pm on Sept 13, 2007 (gmt 0)

Senior Member

WebmasterWorld Senior Member g1smd is a WebmasterWorld Top Contributor of All Time 10+ Year Member Top Contributors Of The Month

joined:July 3, 2002
posts:18903
votes: 0


OK. But what does it DO? What do you use it for?

There must be plenty of beginners looking at it, that consider it would be easier to understand if written in Sanskrit or Swahili!

9:17 pm on Sept 13, 2007 (gmt 0)

Senior Member from US 

WebmasterWorld Senior Member pageoneresults is a WebmasterWorld Top Contributor of All Time 10+ Year Member Top Contributors Of The Month

joined:Apr 27, 2001
posts: 12166
votes: 51


OK. But what does it DO? What do you use it for?

Me too! I'm interested as I'd like to see an asp version if possible.

There must be plenty of beginners looking at it, that consider it would be easier to understand if written in Sanskrit or Swahili!

That makes two of us, so far... :)

9:28 pm on Sept 13, 2007 (gmt 0)

Junior Member

5+ Year Member

joined:Mar 31, 2007
posts:85
votes: 0


Heh, i don't quite understand the usefulness of templates in PHP. I can see using templates in Perl or C++, but i've always thought of PHP, just like JSP, as a templating language in itself so i'm not sure what's gained by adding an extra level of complexity. To me, it's much more straightforward to shove all the relevant values in an associative array and include the php "template" file that generates the HTML based on this array. Can someone please explain the pros and cons of using templates in PHP?
9:29 pm on Sept 13, 2007 (gmt 0)

Full Member

10+ Year Member

joined:Mar 31, 2004
posts:299
votes: 0


errr, what? Can someone break this down to a simple caveman lingo for those that have very limited php knowhow. What is it? A template for a dynamic webpage?
9:50 pm on Sept 13, 2007 (gmt 0)

Senior Member

WebmasterWorld Senior Member 5+ Year Member

joined:July 29, 2007
posts:1525
votes: 9


I've been using global php based templates for years simply because it's the absolute easiest way to make changes to 10,000 pages at once. I was wondering what would happen to global templates now that phpBB forums switched to html, removing yet another way webmasters were being exposed this.

Dunno why I never brought it up here, good job vince!

10:10 pm on Sept 13, 2007 (gmt 0)

Senior Member from US 

WebmasterWorld Senior Member henry0 is a WebmasterWorld Top Contributor of All Time 10+ Year Member

joined:Apr 19, 2003
posts: 4388
votes: 2


VinceVinceVince,
Asides well deserved applauds for a very lean tpl

I can’t say for how long I have been waiting for someone in the PHP forum
to post something that will make the WebmasterWorld top page

More and more when so nicely written in “Swahili!” :)

10:18 pm on Sept 13, 2007 (gmt 0)

Senior Member

WebmasterWorld Senior Member jimbeetle is a WebmasterWorld Top Contributor of All Time 10+ Year Member

joined:Oct 26, 2002
posts:3292
votes: 6


g1smd
But what does it DO? What do you use it for?

P1R

That makes two of us, so far...

Bennie

What is it?

And now me: Duh?

Come on, guys, I know we're strangers in a strange land and don't speak the language, but somebody in here has to be able to translate for us ;-)

11:36 pm on Sept 13, 2007 (gmt 0)

New User

10+ Year Member

joined:Oct 18, 2003
posts:28
votes: 0


This is the one class template engine:

<?php
class Template {
var $data = array();

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

function set($key, $value = NULL) {
if (!is_array($key)) {
$this->data[$key] = $value;
} else {
$this->data = array_merge($this->data, $key);
}
}

function fetch($filename, $directory = DIR_TEMPLATE) {
$file = $directory . $this->directory . '/' . $filename;

if (file_exists($file)) {
extract($this->data);

ob_start();

include($file);

$content = ob_get_contents();

ob_end_clean();

return $content;
} else {
exit('Error: Template ' . $file . ' not found!');
}
}
}
?>

12:54 am on Sept 14, 2007 (gmt 0)

Junior Member

10+ Year Member

joined:June 6, 2005
posts:109
votes: 0


What It Does: It enables you to run a basic templating system to save time, make changes occur easily etc.

Ideally you'd be using it with a database, but you could also just go old-school and make your own pages manually in a couple of different ways.

eg. (building on vince's original example)

Format of template.tpl file:


<html>
<head>
<title>{title}</title>
</head>
<body>
<h1>{header}</h1>
{text}
</body>
</html>

Your 'main' file, let's call it index.php:


<?php
// Figure out which page to load
$page = 'index';
if(!empty($_GET['page']) && ctype_alnum(trim($_GET['page'])))
$page = trim($_GET['page']);
// Get the variables for the page to be loaded
if($page == 'index')
{
$title = 'Index Title';
$header = 'The Great Header';
$text = '<p>all the page\'s text and info</p>';
}
elseif($page == 'about')
{
$title = 'About Us';
$header = 'Info About Us';
$text = '<p>We are the greatest, yada yada</p>';
}
else
{
$title = 'Error: Page Doesn\'t Exist';
$header = 'Sorry, the page you requested doesn\'t exist';
$text = '';
}
// Run the template engine
print preg_replace("/\{([^\{]{1,100}?)\}/e","$$1",file_get_contents("template.tpl"));
?>

The first part checks if a page argument exists, and if it's in a valid alpha-numeric format to keep the hackers out.

The next bits define the variables for each page (including an error page which is displayed if the page argument is in a valid format but isn't actually a page), then you include the template and you're done!

You call the pages by going to:

example.com/index.php or example.com/index.php?page=index
example.com/index.php?page=about

The other way to do it is to put each page in it's own file:

index.php


<?php
$title = 'Index Title';
$header = 'The Great Header';
$text = '<p>all the page\'s text and info</p>';
print preg_replace("/\{([^\{]{1,100}?)\}/e","$$1",file_get_contents("template.tpl"));
?>

about.php

<?php
$title = 'About Us';
$header = 'Info About Us';
$text = '<p>We are the greatest, yada yada</p>';
print preg_replace("/\{([^\{]{1,100}?)\}/e","$$1",file_get_contents("template.tpl"));
?>

Then just load the pages as normal - example.com/index.php, example.com/about.php

HTH

[edited by: MattAU at 1:09 am (utc) on Sep. 14, 2007]

2:28 am on Sept 14, 2007 (gmt 0)

Senior Member from MY 

WebmasterWorld Senior Member vincevincevince is a WebmasterWorld Top Contributor of All Time 10+ Year Member

joined:Apr 1, 2003
posts:4847
votes: 0


Heh, i don't quite understand the usefulness of templates in PHP.

One template, many pages of content. Similar deal to templates used by Dreamweaver etc. but done server-side. Keep your template free of PHP code and you can edit it by nad, or using Dreamweaver, Frontpage or Microsoft Word etc. Just put {} around the things you want to be dynamic (i.e. titles, text, menu,?).

Your PHP file can then be just about PHP code...

contact.php might be just:

$title="Contact us";
if (!$_POST) $text="<form ....> etc...";
else {
$text="Thanks for your contact";
mail("to@example.com","Contact",......);
}
print preg_replace("/\{([^\{]{1,100}?)\}/e","$$1",file_get_contents("template.tpl"));

index.php might be just:

$title="Welcome to Widget Site";
$text="All about widgets ....";
print preg_replace("/\{([^\{]{1,100}?)\}/e","$$1",file_get_contents("template.tpl"));

i.e. every page should be setting $variables matching the {placeholders} you put into the HTML template file (named template.tpl in this example). At the bottom of the PHP file, you call the 'one line template engine' and the magic happens.

Front page thread? Wow!

5:33 am on Sept 14, 2007 (gmt 0)

Senior Member

WebmasterWorld Senior Member 5+ Year Member

joined:July 29, 2007
posts:1525
votes: 9


It's more powerful than just being a "one page" template honestly. You can create different sections of a page and call on them independantly at will. Basicaly an endless variety of pages are possible with just a few lines of code. Php + SQL is worth learning.
6:03 am on Sept 14, 2007 (gmt 0)

Full Member

5+ Year Member

joined:Apr 30, 2006
posts:298
votes: 0


Quite slick, indeed. For me however, I've found that Smarty is quick, robust and pretty full-featured.

Not that I don't see the use of creating your own templating system. My first 4 years of programming I spent re-inventing the wheel. That's how I cut my teeth. The last 3 years of programming I've spent trying to learn how to use the many wheels that came before me. And boy are there a lot of them. Just Zend, Pear, Cake, can fill your learning plate for months.

For those who are unfamiliar with the notion of templates (not a la dreamweaver) this page might be useful: [smarty.php.net...]

6:09 am on Sept 14, 2007 (gmt 0)

Senior Member

WebmasterWorld Senior Member 10+ Year Member

joined:Oct 4, 2001
posts: 1262
votes: 12


Elegant :-)

Significantly less elegant, and untested, alternate using MySQL for greater efficiency:

list($tpl) = mysql_fetch_row(mysql_query("SELECT tpl FROM templates WHERE page = '$self'",mysql_connect($dbh,$dbu,$dbp)));
print preg_replace("/\{([^\{]{1,100}?)\}/e","$$1",$tpl));

Non Swahili translation of greater efficiency: More pages served before you have to buy more hardware.

6:15 am on Sept 14, 2007 (gmt 0)

Preferred Member

10+ Year Member

joined:Jan 10, 2001
posts:562
votes: 0


nice example but personally,I am not a fan of "template" engines - this first example could be done like this and keep it pure php and html, no need to bring the "third" language (saved as .php):

<html>
<head>
<title><?=$title?></title>
</head>
<body>
<h1><?=$header?></h1>
<?=$text?>
</body>
</html>

Setting variables:
$title="Example page";
$header="My Examples";
$text="See the placeholders replaced?";

less code,less files,more understandable and quicker in execution. Or maybe I am missing the "point" of the using template in this particular example? :)

[edited by: JonB at 6:30 am (utc) on Sep. 14, 2007]

6:58 am on Sept 14, 2007 (gmt 0)

Preferred Member

10+ Year Member

joined:May 12, 2004
posts:533
votes: 0


The whole point of the template engine is to keep the logic and the design seperate (or in the case of smarty create a clean happy medium). Yes JonB your example pretty much does the same thing, but your rellying on some basic syntax there that might not be understood by a designer.
7:03 am on Sept 14, 2007 (gmt 0)

Senior Member from MY 

WebmasterWorld Senior Member vincevincevince is a WebmasterWorld Top Contributor of All Time 10+ Year Member

joined:Apr 1, 2003
posts:4847
votes: 0


JonB... your example works, but can you edit it with a WYSIWYG editor? i.e. could you have a designer (not programmer) work on your site design?
This 50 message thread spans 2 pages: 50