using a loop in a template

蓝咒 提交于 2019-12-13 06:32:36

问题


I started writing my own small scaled framework and i have gotten to the templating part of it. So far i have been able to do simple variable replacing with the following code:

public function view($page, $vars)
{
    if(!file_exists('system/views/' . $page . '.php'))
    {
        trigger_error("No Template found", E_USER_ERROR);
    }

    $tempArray = file_get_contents('system/views/' . $page . '.php');

    foreach($vars as $key => $value)
    {
        $tempArray = str_replace('{' . $key . '}', $value, $tempArray);
    }

    print $tempArray;
    unset($tempArray);
}

Which works fine, but what i am looking for now is if i wanted to loop to show unknown number of records from a database and i tried a coupler of ideas but none seem to have worked so far


回答1:


First of all, you should rethink your variable rewriting. There's several cases where your method doesn't end as expected, when you have some dependencies between them. Additionaly, everything gets replaced regardless of a variable being in a loop or not.

If you want something like {while(condition)}code{/while}, you need to be aware that recursion is also possible and therefore it's not as simple as matching a regex on it.

A simple approach would be the following:

  • Find the start of a token (variable, whileloop) and remember the position where you find it
  • If it is a variable and you are in the most outer scope (not in a loop), process it by doing a replacement. Adjust your pointer so that you don't read the replacement afterwards to avoid replacing things that you don't want to.
  • If it is a loop
    • extract the condition between the brackets and store it somewher
    • additionaly, store the current location
    • Push the token onto a stack to remember the current recursion level.
    • Remove a token from the stack when you encounter the {/while} token.
    • Now proceed recursively, pushing all nested loop tokens on the stack and removing them as they end. Stop when you are at the outermost level again.
    • Evaluate the condition of the loop. As long as it is true, create new copies from the source text between the start token and the end token and process them by using recursion.
    • Concatenate the intermediate results and replace everything from {while} to {/while} with this concatenation. Adjust your pointer so that you're pointing after the loop and continue :)

Hope that this helps. I know that it sounds a bit painful, but if you understand the concept, you should be able to do it (although it is not super-efficient and compiling template engines like smarty will always be in advance since they parse the template file just once and compile it to PHP code).

@Daff: you could find the tokens with regular expressions, but using one regex to match on a whole loop construct doesn't work due to the recursions (unless your regex has a recursive extension).




回答2:


As Zed already said there are lots of templating languages for PHP, the most popular one being Smarty and I don't know if it would really make sense to reinvent the wheel except for learning purposes. The loops you want to do are actually way more complex than just replacing elements. I'm pretty sure you can somehow do it with lots of regular expressions, but at some point you will end up with writing your own scripting language (like the Smarty guys did) with parsing your view file, creating a Syntax tree, evaluating it and compile it to a new PHP file. This is quite complex so I recommend to either use an existing templating engine or use PHP as the templating language itself (if strictly folowing the MVC pattern that might work even though there are lots of discussions about that).

With a regular expression you could parse everything between {for ...}{/for} to access an item with a given variable name, where after {for and } a definition of your variable occurrs and after } and before {/for} your html definition. That would be something like a foreach loop which you can't even nest into each other.

{for item=$varname}
    <p>{item.othervalue}</p>
{/for}



回答3:


if your eager to learn this (like i was), you could go to http://net.tutsplus.com/tutorials/php/roll-your-own-templating-system-in-php-new-premium-tutorial/ - this is a tutorial about this, but you need to be plus-member to read it though :)



来源:https://stackoverflow.com/questions/1292970/using-a-loop-in-a-template

标签
易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!