2

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
3
  • If there is no Manufacturer in input string when it is not set, then you can ignore if statement. Just replace anything between [option] and [/option] tiwh values you need and remove anything inside brackets [] Commented Mar 16, 2015 at 11:42
  • 1
    I suggest using some template engine instead of reinventing the wheel. Commented Mar 16, 2015 at 13:45
  • -Do yourself a favour and use a proper templating engine, or even just plain old PHP instead of trying to reinvent the wheel for the 100th time.- What @PeterM Said. Commented Mar 16, 2015 at 14:59

2 Answers 2

2

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.

Sign up to request clarification or add additional context in comments.

1 Comment

Great! That is what I was trying to do. Thank you! I just edit your regex so it is ![if att=\"(.*)\"](.+)[\/if]\<br />!sU that way there are no empty lines (left over <br /> tags) if there is no option set.
1
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

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.