简体   繁体   中英

Replace shortcodes with regex in php

I have a custom PHP script with template text that looks like this

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

I have used preg_replace_callback to successfully replace [option]color[/option] and [option]price[/option] with real values like White and $10.00.

I am using this code for simple [option] shortcodes:

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

                                    return $some_value;
                                },
                                $template);

But I just can`t figure out what to do with IF statements... It should check if the manufacturer is set and then replace [option]manufacturer[/option] and of course also remove the opening and closing if line.

Result output should be

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

Or if there is no manufacturer defined it should be

Color: White<br />
Price: $10.00

For the if , you should add a second preg_replace_callback`, and use the it as follows:

$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
);

What you should notice here are the modifiers sU at the end of the regexp.

The s makes the dots . in the regex also include newlines, so the regexp can look beyond just the same line.

The U makes the regex ungreedy. And you will need this, otherwise your regex might start on the beginning of the first shorttag and last until the end of the last shorttag, for just one occurance. You haven't faced this problem yet, because you don't have two shorttags on the same line anywhere. But the s modifier will now introduce that problem.

And off course also notice there are now two groups that get matched. First one is the option in the if , and the second one is the contents of the if .

Lastly I would advice you to not get the values inside your anonymous function, as the anonymous function will be called over and over for each shorttag. This will give you overhead. Rather get the values outsid of the anonymous function and pass the values along, using the use keyword.

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

It produce following output:

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

If the value 'Manufacturer' is empty means the output became:

Color: White <br />
Price: $10.00

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM