3

I'm getting stuck at this problem, which is

I have an array like this:

$array = [
    'name' => 'John',
    'email' => john@gmail.com
];

And a string sample like this:

$string = 'Hi [[name]], your email is [[email]]';

The problem is obvious, replace name with John and email with john@gmail.com.

What i attempted:

//check if $string has [[ ]] pattern

$stringHasBrackets = preg_match_all('/\[\[(.*?)\]\]/i', $string,  $matchOutput);

if ($stringHasBrackets) {

    foreach ($matchOutput[1] as $matchOutputKey => $stringToBeReplaced) {

        if (array_key_exists($stringToBeReplaced, $array)) {

            $newString = preg_replace("/\[\[(.+?)\]\]/i",
                            $array[$stringToBeReplaced],
                            $string);

        }
    }
}

Which led me to a new string like this:

Hi john@gmail.com, your email is john@gmail.com

Makes sense because that's what the pattern is for, but not what I wanted.

How can I solve this? I thought of using a variable in the pattern but don't know how to do it. I've read about preg_replace_callback but also don't really know how to implement it.

Thanks!

M. Eriksson
  • 13,450
  • 4
  • 29
  • 40
Duong Nguyen
  • 149
  • 4
  • 12

4 Answers4

3

preg_replace accepts arrays as regex and replacement so you can use this simpler approach:

$array = ['name' => 'John', 'email' => 'john@gmail.com'];
$string = 'Hi [[name]], your email is [[email]]';

// create array of regex using array keys
$rearr = array_map(function($k) { return '/\[\[' . $k . ']]/'; },
         array_keys($array));

# pass 2 arrays to preg_replace
echo preg_replace($rearr, $array, $string) . '\n';

Output:

Hi John, your email is john@gmail.com

PHP Code Demo

anubhava
  • 761,203
  • 64
  • 569
  • 643
3

You may use preg_replace_callback like this:

$array = ['name' => 'John', 'email' => 'john@gmail.com'];
$string = 'Hi [[name]], your email is [[email]]';
echo preg_replace_callback('/\[\[(.*?)]]/', function ($m) use ($array) {
        return isset($array[$m[1]]) ? $array[$m[1]] : $m[0]; 
    }, $string);

See PHP demo.

Details

  • '/\[\[(.*?)]]/' matches [[...]] substrings putting what is inside the brackets into Group 1
  • $m holds the match object
  • use ($array) allows the callback to access $array variable
  • isset($array[$m[1]]) checks if there is a value corresponding to the found key in the $array variable. If it is found, the value is returned, else, the found match is pasted back.
Wiktor Stribiżew
  • 607,720
  • 39
  • 448
  • 563
  • Nice answer +1 @DuongNguyen But because running regex is pretty expensive operation . i would include a if to check if the string contains a replace templates checking on `[[` and `]]` see demo https://ideone.com/K4hKmJ .. Nicer would be offcource to make a function – Raymond Nijland Aug 21 '18 at 11:28
  • Thanks. Will do a research on preg_replace_callback and get back to you if this works. @RaymondNijland I checked the string with preg_match_all, is it alright? – Duong Nguyen Aug 21 '18 at 12:46
  • "I checked the string with preg_match_all, is it alright?" @DuongNguyen `preg_match_all` still uses regexes now you start up two regex engines. – Raymond Nijland Aug 21 '18 at 12:48
  • @RaymondNijland I see. – Duong Nguyen Aug 21 '18 at 13:00
1

You can try this,

$array = ['name' => 'John', 'email' => 'john@gmail.com'];
$string = 'Hi [[name]], your email is [[email]]';
$stringHasBrackets = preg_match_all('/\[\[(.*?)\]\]/i', $string,  $matchOutput);

if ($stringHasBrackets) {
    $newString = $string;
    foreach ($matchOutput[1] as $matchOutputKey => $stringToBeReplaced) {
        if (array_key_exists($stringToBeReplaced, $array)) {
            $newString = preg_replace("/\[\[$stringToBeReplaced\]\]/i", $array[$stringToBeReplaced], $newString);
        }
    }
    echo $newString;
}
Yogesh Salvi
  • 1,177
  • 2
  • 10
  • 17
1

I think here more simply would be to use str_replace function, like:

$array = [
          'name' => 'John',
          'email' => 'john@gmail.com'
          ];

$string = 'Hi [[name]], your email is [[email]]';
$string = str_replace(array_map(function ($v) {return "[[{$v}]]";}, 
                      array_keys($array)), $array, $string);
echo $string;

Updated for $array to be "untouchable"

Agnius Vasiliauskas
  • 10,935
  • 5
  • 50
  • 70
  • This can be much simpler than using regex, but I'm not allowed to touch the array, and array_keys returns an array, so can I somehow concatenate [[ and ]] to it? Also, I want to replace array_keys($array) in the string with array values. – Duong Nguyen Aug 21 '18 at 12:54
  • see updated version - in this case we need `array_map` also. And yes - it searches in string for modified keys and replaces with array values – Agnius Vasiliauskas Aug 21 '18 at 13:03
  • Thank you Agnius! – Duong Nguyen Aug 21 '18 at 13:16