0

I have a PHP variable that contains HTML. I need to check for occourances of a string, and have that string replaced with the result of a function.

The function has not yet been written, but will only require one variable passed to it which will be the ID of the product.

For instance, the website has products, I want the user to be able to type something into the wysiwyg editor like {{product=68}} and it will display a preset div container with the information for that product. In this case the product has ID 68 in the database, but it could be anything from 1 to whatever.

I thought about creating an array of product id's and searching for the first part of the string, but felt it may be rather cumbersome, I think one of our resident reg exp genius may be able to shed some light on what i need to do.

So the question is... how do i search a string for occourances of {{product=XXX}} where XXX can be an integer higher than one, capture that number, and pass it to a function which creates the replacement string which ultimatley replaces the occourance of the string ?

4
  • What if the content writer may spell a product name differently ? If you have too many products, this can occur Commented Jan 17, 2013 at 12:37
  • We don't use greetings and 'Thanks in advance' here on SO as it is just noise around the question. That is why I edited them out. However, I see you've put them back. Your call, but somebody else is likely to do the same :) Commented Jan 17, 2013 at 12:41
  • the only thing they have to enter is the ID for the product, a number, which is given to them via the content management system. I would assume that if they spell something wrong with the 'needle' then it wouldn't trigger the function, or simply be replaced with nothing. Commented Jan 17, 2013 at 12:41
  • vascowhite - i was editing the question before, you must have pressed save before me. sorry about that :/ Commented Jan 17, 2013 at 12:43

2 Answers 2

1

Here is a regexp that matches {{product=##}} (doesn't matter how many digits you enter):

{{product=([0-9]+)}}

Edit: Sorry, didn't see you wanted it starting with 1:

{{product=([1-9][0-9]*)}}

If you want to capture the number, to it like this:

$string = '{{product=68}}';
preg_match_all( '%{{product=([1-9][0-9]*)}}%', $string, $matches );
$number = (int) $matches[1][0];

To give you a better understanding of preg_match_all, this is the content of $matches:

array
  [0] => array // An array with strings that matched the whole regexp
    [0] => '{{product=68}}'
  [1] => array // An array with strings that were in the first "match group", indicated by paranthesis in the regexp
    [0] => '68'

E.g. $matches would look like this if you had the string '{{product=68}}{{product=70}}':

array
  [0] => array
    [0] => '{{product=68}}'
    [1] => '{{product=70}}'
  [1] => array
    [0] => '68'
    [1] => '70'
Sign up to request clarification or add additional context in comments.

9 Comments

thanks, looks good, how do I "capture" the number inside the string, would I have to play with the string after finding it or can it be isolated when it's encountered ?
would i need to use preg_replace_callback() ?
I posted the function for you.
so, for every item in array(0) is an encountered string, and the array(1) is the number from that string, lets say i iterate array(1) and create an array of html at array(2), which will be the html to insert into the string, how do i then insert those.. ? with something as simple as str_replace ?
Oh sorry, I misunderstood your question a bit! preg_replace_callback would indeed be the shortest solution in this case. Shall I update my example?
|
1

Made a small class for you, that should do what you need.

<?php
class textParser{
    const _pattern = '/{{([a-z\-_]+)=([0-9]+)}}/';
    static protected $_data = false;

    static public function setData($data){
        self::$_data = $data;
    }
    static function parseStr($str){
        // Does a preg_replace according to the 'replace' callback, on all the matches
        return preg_replace_callback(self::_pattern, 'self::replace', $str);
    }
    protected static function replace($matches){
        // For instance, if string was {{product=1}}, we check if self::$_data['product'][1] is set
        // If it is, we return that
        if(isset(self::$_data[$matches[1]][$matches[2]])){
            return self::$_data[$matches[1]][$matches[2]];
        }
        // Otherwise, we just return the matched string
        return $matches[0];
    }
}
?>

Unit test / Basic usage

<?php
// User generated text-string
$text = "Item {{product=1}} and another {{category=4}} and a category that doesnt exist: {{category=15}}";
// This should probably come from a database or something
$data = array(
    "product"=>array(
        1=>"<div>Table</div>"
      , 2=>"<div>Tablecloth</div>"
    )
  , "category"=>array(
        4=>"Category stuff"
    )
);
// Setting the data
textParser::setData($data);
// Parsing and echoing
$formated = textParser::parseStr($text);
echo $formated;
// Item <div>Table</div> and another Category stuff and a category that doesnt exist: {{category=15}}
?>

1 Comment

this looks meaty ! im going to integrate it and test it out later today :D Thanks !

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.