在 php 中用正则表达式替换短代码


Replace shortcodes with regex in php

我有一个自定义的PHP脚本,其中包含如下所示的模板文本

Color: [option]color[/option]<br />
[if option="manufacturer"]<br />
Manufacturer: [option]manufacturer[/option]<br />
[/if]<br />
Price: [option]price[/option]

我使用preg_replace_callback成功地将 [option]color[/option] 和 [option]price[/option] 替换为 White 和 $10.00 等实际值。

我将此代码用于简单的 [选项] 短代码:

$template = preg_replace_callback('!'[option]('w+)'['/option']!',
                                function ($matches)
                                {
                                    //Here I get a value of color, price, etc
                                    ...
                                    return $some_value;
                                },
                                $template);

但我就是不知道如何处理 IF 语句......它应该检查制造商是否已设置,然后替换[选项]制造商[/选项],当然还要删除打开和关闭if行。

结果输出应为

Color: White<br />
Manufacturer: Apple<br />
Price: $10.00

或者,如果没有定义制造商,则应为

Color: White<br />
Price: $10.00

对于if,您应该添加第二个preg_replace_callback',并按如下方式使用它:

$options['color'] = 'white';
$options['price'] = '10.00';
$template = preg_replace_callback(
    '!'[if option='"(.*)'"'](.+)'['/if']!sU',
    function ($matches) use ($options)
    {
        if (isset($options[$matches[1]]))
            return $matches[2];
        else
            return '';
    },
    $template
);

您应该注意的是正则表达式末尾sU修饰符。

s使正则表达式中.的点还包括换行符,因此正则表达式可以超越同一行。

U使正则表达式不贪婪。您将需要这个,否则您的正则表达式可能会从第一个短标签的开头开始,一直持续到最后一个短标签的末尾,只出现一次。您还没有遇到这个问题,因为您在任何地方都没有在同一行上有两个短标签。但是s修饰符现在将引入该问题。

当然,还注意到现在有两组被匹配。第一个是if中的选项,第二个是if的内容。

最后,我建议您不要在匿名函数中获取值,因为每个短标签都会一遍又一遍地调用匿名函数。这将为您提供开销。而是获取匿名函数的值,并使用 use 关键字传递值。

class test {
    protected $color = 'White';
    protected $manufacturer = 'Apple';
    protected $price = '$10.00';
    public function __construct() {
        $template = '[option]color[/option]
                    [option]manufacturer[/option]
                    [option]price[/option]';
        $temp = preg_replace_callback('!'[option]('w+)'['/option']!',
                                        function ($matches)
                                        {
                                            $value = !empty($this->$matches[1]) ? ucfirst($matches[1]) . ': ' . $this->$matches[1] . '<br />' : '';
                                            return $value;
                                        },
                                        $template);
        echo $temp;
    }
}
new test;  // call the constructor function

它产生以下输出:

Color: White <br /> 
Manufacturer: Apple <br />
Price: $10.00

如果值"制造商"为空,则表示输出变为:

Color: White <br />
Price: $10.00