4

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?

4
  • have you tried some code already? please add sample code and output. Commented Dec 4, 2010 at 14:27
  • 1
    Did you notice that this "template engine" only replaces <?=$ (or <?php echo $ into {{ and ` ?>` into }}? You're just creating dozens of new problems rather solving any. Commented Dec 4, 2010 at 14:45
  • 1
    As long as you have to ask such questions, you shouldn't go into designing your own templating system, but reuse some of the existing ones which were built by experienced developers. Commented Dec 4, 2010 at 16:54
  • PHP is a template system. Use PHP. You cannot write a better template system in PHP than PHP itself. Commented Dec 4, 2010 at 22:43

6 Answers 6

2

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');"

example of 'template.inc':

<ul>
    <?foreach ($items as $item){?>
    <li>
        <img src="/album/<?=$item[filename]?>" alt="">
        <span><?=$item[imgname]?></span>
    </li>
    <?}?>
</ul>

Sign up to request clarification or add additional context in comments.

2 Comments

designers aren't as good with this. why trust them with PHP code?! by far and away, my advice is to always always use PLAIN TEXT templates.
On the other hand - smarty template engine was made to simplify designer's life. But its tags {foreach from=... item=...} aren't much more easier than <?foreach (...)?> So why use smarty or any other template engine? I suppose designers aren't so dumb to be not able to learn some main php tags :) What do you mean by PLAIN TEXT templates?
2

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") ?>

2 Comments

+1 for "use PHP". Also, don't use a double underscore prefix for your names. They're reserved for PHP.
@Meagar, Firstly that's for the up vote, and using double underscores would have no effect here because firstly there variables, and i dont think PHP Has any magic vars, secondly im specifically looking in the object scope, i.e $this->, the reason for the underscores is because as there's a magic method for setting data to the array I don't want the user to set content called data as it would override the container.
0

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.

6 Comments

I want to create everything myself in this project, and this shouldn't really be that hard, right? I mean, it doesn't look very complicated - it's just a matter of finding a way to do it. It also feels kind of unnecessary to use a template engine like smarty for my project. It's unnecessarily big for what i need it for.
@ajreal Django templates, Mustache and several other templating systems use the double curly brace syntax, as well.
@asdf: "this shouldn't really be that hard" is overly optimistic, if not shortsighted. you're not into conditionals and other types of loops yet.
@stillstanding: Being optimistic is good. And i still believe it isn't that hard, there's probably a ton of different solutions for this, and some of them will be simple. @ajreal: I have a good reason for using it. So you're saying people can't ask simple questions?
@asdf go for it, it's a great exercise. how hard it is depends on features. but don't think supporting expressions is an easy task - quite nontrivial. especially without using PHP/eval.
|
0

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.

Comments

0

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.

Comments

-3

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.

6 Comments

I thought of something like that, but i didn't manage to eval() it because of the html code around it. How would that work? Example?
Downvote for crazy idea of compiling template each time and using eval().
@stereofrog, that does work. But in your first post you suggested me to add chunks of php code (like <?php foreach(...) : ?>), and then evaluate it. After editing your post you just replaced {{name}} with $name. As i said before, the complex part about this is making it run a loop. Could you give me better example of running a loop and echoing out an array? Thanks a lot! @Col; You often comment on other peoples suggestions, but you never help. Why is that?
OMG, who would do such a thing :(, this should never be used, especially in template systems.. -1
"eval is evil" only if it affects performance and input is from end-user. obviously, templates are not end-user provided.
|

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.