如果在带有正则表达式的PHP模板引擎中,则为多个

问题描述 投票:0回答:1

首先,对不起我的英语不好。

我正在尝试使用正则表达式和preg_match_all创建一个PHP模板引擎。

我的正则表达式看起来像:

/\{:[\s]*?[\n]*?[\s]*?if(.*?):\}[\s]*?(.*?)[\s]*?(\{:[\s]?else[\s]?:\}[\s]*?(.*?)[\s]*?)\{:[\s]*?endif[\s]*?:\}/is

我的PHP看起来像:

preg_match_all('/\{:[\s]*?[\n]*?[\s]*?if(.*?):\}[\s]*?(.*?)[\s]*?(\{:[\s]?else[\s]?:\}[\s]*?(.*?)[\s]*?)\{:[\s]*?endif[\s]*?:\}/is', $template, $regs, PREG_PATTERN_ORDER);


for ($i = 0, $iMax = count($regs[0]); $i < $iMax; $i++) {
    $condition = $regs[1][$i];
    $trueval   = $regs[2][$i];
    $falseval  = $regs[4][$i] ?? false;
    $res = eval('return ('.$condition.');');

    if ($res===true) {
        $template = str_replace($regs[0][$i],$trueval,$template);

    } else {
        $template = str_replace($regs[0][$i],$falseval,$template);
    }
}

在我的模板字符串中,如果只有一个,则是这样的:

{: if $var > 3 :}
    The variable $var is > than 3
{: else :}
    The variable $var is < than 3
{: endif :}

它会很好地工作。但是,如果我在其中放置另一个,则将不起作用。

{: if $var > 3 :}
    The variable $var is > than 3
    {: if $var1 < 2 :}
        The variable $var1 < than 2
    {: else :}
        The variable $var1 > than 2
    {: endif :}
{: else :}
    The variable $var is < than 3
{: endif :}

在这种情况下,preg match全部将无法正常工作,并且将向我输出此内容:

{: if $var > 3 :}
    The variable $var is > than 3
    {: if $var1 < 2 :}
        The variable $var1 is < than 2
    {: else :}
        The variable $var1 is > than 2
    {: endif :}

它将停止在第一个端点,而不是一个好的端点。我绝对不知道该怎么做。如果有人有想法?非常感谢您的时间和帮助!

php regex if-statement templates preg-match-all
1个回答
0
投票

我找到了一个解决方案,没有使用任何正则表达式。我不知道这是否是最佳做法,但是可以。

首先,我逐行拆分文本:

$text = explode(PHP_EOL, $text);

接下来,我在此$ text上进行学习:

        $if = [];
    foreach ($test as $key => $line){
        if(StringUtils::contains($line, 'if') && (!StringUtils::contains($line, 'endif'))){
            $if[$key] = trim($line);
        }
    }

正如您所看到的,我正在本文中寻找某些内容,并将它们放入具有键行号的数组中。

接下来,我进行最后的学习,检查条件,然后替换所有:

        krsort($if);

    $var = 4;
    $var1 = 1;
    foreach ($if as $ifOffset => $ix){
        for($i = $ifOffset, $iMax = count($test); $i<$iMax; $i++){
            if(StringUtils::contains($test[$i], 'endif')){
                $content = StringUtils::getBetween($text, $test[$ifOffset], $test[$i]);
                $cond = trim(str_replace('if', '', StringUtils::getBetween($ix, '{:', ':}')));
                $res = eval('return ('.$cond.');');

                $ph = $test[$ifOffset].$content.$test[$i];

                if($res===true){
                    $text = str_replace($ph, $content, $text);
                }else{
                    $text = str_replace($ph, '', $text);
                }
                unset($if[$ifOffset]);
                break;
            }
        }
    }

$ var和$ var1是我在条件中使用的变量。现在,这个:

    {:if $var > 3 :}

    <p>Bienvenue {{user}} !</p>

{:if $var1 < 2 :}
<p>Wow ! Tu as la permission !</p>
{:endif:}

{:endif:}

{:if $var > 3 :}

<p>Bienvenue {{user}} !</p>

{:if $var1 < 2 :}
<p>Wow ! Tu as la permission !</p>
{:endif:}

{:endif:}

将输出:

Bienvenue {{user}} !

Wow ! Tu as la permission !

Bienvenue {{user}} !

Wow ! Tu as la permission !

我们在这里!

对于“ StringUtils :: contains”函数,您可以使用:

    public static function contains($text, ...$search){
    if(!empty($search)){
        foreach($search as $key => $value){
            if(strpos($text, $value) !== false){
                unset($search, $text, $key, $value);
                return true;
                break;
            }
        }
        unset($search, $text);
    }
    return false;
}

如果有人有更好的主意,为什么不这样做,但是效果很好!

© www.soinside.com 2019 - 2024. All rights reserved.