3

How can I parse, let's say, {if $var > 2} or {if $var} in a .tpl file in my own version of a templating class. I do not wanna use smarty as I don't need all their plugins. I just want include, if, for and foreach statements.

Chris Pfohl
  • 18,220
  • 9
  • 68
  • 111
Speedy Wap
  • 478
  • 4
  • 7
  • 18
  • 3
    Unless this is for learning purposes (which I doubt because you want the code), I would use Smarty (remove the plugins if you don't need them) or native PHP. No need to reinvent a wheel that has been invented thousands of times already – Pekka Feb 09 '11 at 10:37
  • If you don't want to use Smarty, that does not exclude it from being used as reference for implementation details. They are using regular expressions to transform the template pseudo code to php. – mario Feb 09 '11 at 10:40
  • i am doing this for learning purposes but finding it quite hard to get my head around it. So instead of using smarty I want to create my own templating system so I have a better understanding how templating works. – Speedy Wap Feb 09 '11 at 10:53
  • 5
    Once you start going down this route, your templating language becomes a programming language. There is nothing wrong with this (Template-Toolkit is a thing of beauty), but writing a programing language is not something for the faint hearted. I'd start by reading up on interpretor theory. – Quentin Feb 09 '11 at 12:22
  • I think you should use Smarty. If you don't, your hand-made solution will be (a) buggy, and (b) _way_ more complex than just using Smarty, even if you don't use their plugins. And, let's face it, if you don't want to use their plugins... then you don't have to. – Lightness Races in Orbit Feb 21 '11 at 23:18

6 Answers6

13

Please use php. Just put in your tpl file:

<?php if ($var > 2) .... ?> 

It's a lot simpler, less code and a lot faster than parsing the file in php

AntonioCS
  • 8,335
  • 18
  • 63
  • 92
10

use

<? if( condition ) :
    ....
    ....
else : 
    ....
    ....
endif; ?>

Difference between if () { } and if () : endif;

Community
  • 1
  • 1
Gaurav
  • 28,447
  • 8
  • 50
  • 80
6

You already got the answer with your last question: if statements in php templates using tpl
But since you won't go away otherwise, let me quickly answer it and then mention which will be your certain next stumbling blocks.

// handle {if}...{/if} blocks
$content =
preg_replace_callback('#\{if\s(.+?)}(.+?)\{/if}#s', "tmpl_if", $content);

function tmpl_if ($match) {
    list($uu, $if, $inner_content) = $match;

    // eval for the lazy!
    $if = create_function("", "extract(\$GLOBALS['tvars']); return ($if);");

    // a real templating engine would chain to other/central handlers
    if ( $if() ) {
        return $inner_content;
    }
    # else return empty content
}

Using a regular expression like this will trip over a nested if. But you didn't ask about that, so I won't mention it. And as outlined in the comment you would actually need to chain to a central function that does further replacements ({foreach} / {include} / etc.) instead of just return $content as here.

This is doable, but quickly growing cumbersome. And this is why all other templating engines (which you refuse to check out) actually convert .tpl files into .php scripts. That's much easier because PHP can already handle all those control structures that you try to mimick with your own templating class.

Community
  • 1
  • 1
mario
  • 144,265
  • 20
  • 237
  • 291
  • how could that then possibly converted to php. – Speedy Wap Feb 16 '11 at 22:49
  • @user381595: With regular expressions. Converting each `{if ...}` into `` and each `{/if}` into `` for example. – mario Feb 16 '11 at 22:57
  • @SpeedyWap: Yes it probably would. Hencewhy many solutions are already dicoverable with the search function. http://stackoverflow.com/questions/3930053/dirt-simple-php-templates-can-this-work-without-eval – mario Feb 17 '11 at 00:07
5

Actually it's pretty simple unless you need nested if conditions.

$template = '<b>{foo}</b>{if bar} lorem ipsum {bar}{/if}....';

$markers = array(
    'foo' => 'hello',
    'bar' => 'dolor sit amet',  
);

// 1. replace all markers 
foreach($markers as $marker => $value)
    $template = str_replace('{'. $marker .'}', $value, $template);

//2. process if conditions
$template = preg_replace_callback('#\{if\s(.+?)}(.+?)\{/if}#s', function($matches) use ($markers) {

    list($condition, $variable, $content) = $matches;

    if(isset($markers[$variable]) && $markers[$variable]) {
        // if the variable exists in the markers and is "truthy", return the content
        return $content;
    }

}, $template);
Alex
  • 12,205
  • 7
  • 42
  • 52
0

There is an php code example that parses following temaplate (php 5.3+):

[IF {post_content}]Post content is filled![ENDIF]
[IF {post_content}]Post content is filled![ELSE]{post_content}[ENDIF]

Code:

$tags = array('post_content'=>'POST_CONTENT');

$message = '1: [IF {post_content}]Post content: {post_content}![ENDIF]
            2: [IF {post_content}]Post content is filled![ELSE]Post content is empty![ENDIF]';

$matches = array();

preg_match_all('/\[IF \{([^\}]*)\}\](.[^\]]+)(?:\[ELSE\](.+?))?\[ENDIF\]/s', $message, $matches);

if ( empty($matches) ) {
    return $message;
}

$math_tag = '';
foreach ( $matches[0] as $m_index => $match )
{
    $math_tag =  trim($matches[1][$m_index]);

    if ( !empty($tags[$math_tag]) ) {
        // IF value is not empty
        $message = str_replace($match, $matches[2][$m_index], $message);
    } elseif( empty($tags[$math_tag]) && $matches[3][$m_index] ) {
        // ELSE
        $message = str_replace($match, $matches[3][$m_index], $message);
    } else {
        // IF NO ELSE condition - REMOVE ALL
        $message = str_replace($match, '', $message);
    }
}

foreach($tags as $tag => $value)
   $message = str_replace('{'. $tag .'}', $value, $message);

echo $message;
MaxWell99
  • 26
  • 3
0

You can use the following format into your template file(.tpl).,

{if $url == 'error'}
Error message Invalid Login!
{/if} 
Rajesh
  • 421
  • 1
  • 5
  • 20