Несколько, если в PHP шаблонизатор с Regex - PullRequest
0 голосов
/ 23 апреля 2020

Прежде всего, извините за мой довольно плохой engli sh.

Я пытаюсь создать шаблонный движок PHP, используя regex & preg_match_all.

Мой regex выглядит так:

/\{:[\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, что-то вроде этого:

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

It будет работать отлично. Но если в этом, если я поставлю другой if, он не будет работать.

{: 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 all не будет работать должным образом и выдаст мне следующее:

{: 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 :}

Это остановится на первом конце, а не на хорошем. Я понятия не имею, как это сделать. Если у кого-то есть идея? Большое спасибо за ваше время и вашу помощь!

1 Ответ

0 голосов
/ 23 апреля 2020

Я нашел решение без использования регулярных выражений. Я не знаю, является ли это наилучшей практикой, но она работает.

Прежде всего, я разбил текст на строку:

$text = explode(PHP_EOL, $text);

Далее я рассмотрю этот текст $ :

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

Как вы можете видеть, я ищу некоторые слова в этом тексте и помещаю их в массив с номером строки для ключа.

Далее я сделайте последний foreach, проверьте условие и замените все:

        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 :: Содержит", вы go:

    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;
}

Если у кого-то есть идея получше, почему бы и нет, но она работает хорошо!

...