Reputation: 5246
I've already searched here and surprisingly i didn't find the answer. I found one similar thread, but no real solution there. The complicated part is the loop, if i didn't need the loop i could just do a regular replace.
So, i have a .html file with some markup, like this:
<ul>
{{startloop}}
<li>
<img src="/album/{{filename}}" alt="">
<span>{{imgname}}</span>
</li>
{{endLoop}}
</ul>
What i want to do is replace {{filename}} and {{imgname}} with something else. I know how to do that, but the thing is, i want it inside a loop. So for each looped item {{filename}} and {{imgname}} will be different. If i have two "items", it'll look like this (just an example):
<ul>
<li>
<img src="/album/image1.jpg" alt="">
<span>Test name 1</span>
</li>
<li>
<img src="/album/image2.jpg" alt="">
<span>Test name 2</span>
</li>
</ul>
Any suggestions?
Upvotes: 4
Views: 452
Reputation: 53940
Replace your {{tags}} with chunks of php code (foreach
in this case) and then eval
the result. This is how php template engines work.
example:
$template = "<h1>Hello {{name}}</h1>";
$name = "Joe";
$compiled_template = preg_replace(
'~{{(.+?)}}~',
'<?php echo $$1 ?>',
$template);
eval('?>' . $compiled_template);
prints <h1>Hello Joe</h1>
A more advanced example, involving arrays and loops
$template = "
{{each user}}
{{name}} {{age}}<br>
{{end}}
";
$user = array(
array('name' => 'Joe', 'age' => 20),
array('name' => 'Bill', 'age' => 30),
array('name' => 'Linda', 'age' => 40),
);
$t = $template;
$t = preg_replace(
'~{{each (\w+)}}~',
'<?php foreach($$1 as $item) { ?>',
$t);
$t = preg_replace(
'~{{end}}~',
'<?php } ?>',
$t);
$t = preg_replace(
'~{{(\w+)}}~',
'<?php echo htmlspecialchars($item["$1"]) ?>',
$t);
eval('?>' . $t);
In response to other comments, telling me that "php is a template engine" and "eval is evil" - people, don't repeat stupid mantras you've heard somewhere. Try to think on your own.
Upvotes: -3
Reputation: 1630
The only way to create a superfast template system is to rely on PHP as a parser, or through the use of an extension coded in C. Furthermore, there's probably no reason to attempt this in any case, as it's already been done a thousand times. There's lots of big winners out there like Smarty, though performance isn't stellar. The template system in PHPBB is also pretty good (using pre-parse and cached PHP). Avoid re-inventing a wheel here.
If performance is a major concern, I highly recommend Blitz.
Borrowing from PHPBB is another route. If you don't have access to extend PHP on your server, and Smarty isn't your cup of tea on format of performance, and would like all the bare-metal code, you could do like me and rip out what's in PHPBB. It isn't the end-all solution, and full of particulars, but it's quite good -- and with the source, you can customize it to taste. It eval's to code so supports some level of expressions, and supports HTML comment tags as the template escapes/markers that are user-friendly for less techie graphic designers.
Upvotes: 0
Reputation: 57268
Don't create a parser as its totally pointless, PHP is already a template engine, all you want to do is extend its capabilities with encapsulated template system.
The method below is the way I always create my template engine, its very lose, and can be extended with template helpers as such.
a good thing about my template system is that you don't have to waste your resources creating a cache system for your compiled templates as there already in a compiled state, comparing to engines like smarty.
Firstly we want to create a the main template class which would be used for setting data, and selecting the template etc.
So lets get started with this:
class Template
{
private $__data = array();
public function __construct(){/*Set up template root here*/}
public function __set($key,$val)
{
$this->__data[$key] => $val;
}
public function __get($key)
{
return $this->__data[$key];
}
public function Display($Template)
{
new TemplatePage($Template,$this->__data); //Send data and template name to encapsulated object
}
}
this is a very basic class that will allow is do do something like
$Template = new Template();
$Template->Userdata = $User->GetUserData();
$Template->Display("frontend/index");
Ok now you might have noticed the class above called TemplatePage
, this is the class that loads the actual file template, and within the actual template you would be in the scope of the TemplatePage
scope.
This will will allow you to have methods to get your template data and also access helpers, below is an example of a TemplatePage
class TemplatePage
{
private $__data = array();
public function __construct($template,$data)
{
$this->__data = $data;
unset($data);
//Load the templates
if(file_exists(TEMPLATE_PATH . "/" . $template . ".php"))
{
require_once TEMPLATE_PATH . "/" . $template . ".php";
return;
}
trigger_error("Template does not exists",E_USER_ERROR);
}
public function __get($key)
{
return $this->__data[$key];
}
public function require($template)
{
if(file_exists(TEMPLATE_PATH . "/" . $template . ".php"))
{
require_once TEMPLATE_PATH . "/" . $template . ".php";
return;
}
trigger_error("Template does not exists",E_USER_NOTICE);
}
public function link($link,$title)
{
return sprintf('<a href="%s">%s</a>',$link,$title);
}
}
So now as the template is loaded within the scope of the class you can extend the methods such as link
and require
to have a fully function template tool-kit
Example of template:
<?php $this->require("folder/js_modules") ?>
<ul>
<?php foreach ($this->photos as $photo): ?>
<li>
<?php echo $this->link($photo->link,"click to view") ?>
<span><?php echo $photo->image_name?></span>
</li>
<?php endforeach; ?>
</ul>
<?php $this->require("folder/footer") ?>
Upvotes: 2
Reputation: 1768
Maybe the better thing to do here is to use the MVC/MVVVM patterns and then you get this for free along with a very structured and organized code project.
Take a look at this page from Rasmus' blog as a primer to this workflow: http://toys.lerdorf.com/archives/38-The-no-framework-PHP-MVC-framework.html
If you are willing to let go of the reigns a bit, Zend is very good as a framework and can help you get your site done pretty quickly. It will save you having to rewrite a lot of code yourself and give you some advanced features you probably wouldn't want to have to write on your own anyway.
I wholeheartedly agree with you about the size of some frameworks, and you can do this without them. The trade-off is time. Time spent coding and time spent debugging. Like I said, if you're willing to let go of some control you can breeze through your project only having to deal with debugging the 'business logic' of your site and not having to reinvent a lot of already existing code.
Hope this is helpful.
Upvotes: 0
Reputation: 3843
I was a big fan of "smarty" template engine for a long time until the moment I realised I don't need it at all :) It's much better and faster to user straight inline php tags.
just put you html+php_tags into 'some_template.inc' file instead of html file.
then show this template by "include('template.inc');"
<ul>
<?foreach ($items as $item){?>
<li>
<img src="/album/<?=$item[filename]?>" alt="">
<span><?=$item[imgname]?></span>
</li>
<?}?>
</ul>
Upvotes: 2
Reputation: 1707
Is there any reason you're making your own templates system? I'd recommend using Smarty http://www.smarty.net/
It has this functionality already as well as a lot more, such as caching etc.
Upvotes: 0