Duong Nguyen
Duong Nguyen

Reputation: 159

Replace with dynamic variable in preg_replace

I'm getting stuck at this problem, which is

I have an array like this:

$array = [
    'name' => 'John',
    'email' => [email protected]
];

And a string sample like this:

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

The problem is obvious, replace name with John and email with [email protected].

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 [email protected], your email is [email protected]

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!

Upvotes: 3

Views: 2572

Answers (4)

anubhava
anubhava

Reputation: 786349

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

$array = ['name' => 'John', 'email' => '[email protected]'];
$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 [email protected]

PHP Code Demo

Upvotes: 3

Agnius Vasiliauskas
Agnius Vasiliauskas

Reputation: 11277

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

$array = [
          'name' => 'John',
          'email' => '[email protected]'
          ];

$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"

Upvotes: 1

Yogesh Salvi
Yogesh Salvi

Reputation: 1212

You can try this,

$array = ['name' => 'John', 'email' => '[email protected]'];
$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;
}

Upvotes: 1

Wiktor Stribiżew
Wiktor Stribiżew

Reputation: 627609

You may use preg_replace_callback like this:

$array = ['name' => 'John', 'email' => '[email protected]'];
$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.

Upvotes: 4

Related Questions