0
$message = "[Link] Thanks [Link]";
echo str_replace(
array("[Link]", "[Link]"), 
array("mylink1", "mylink2"), 
$message
);

prints: "mylink1 Thanks mylink1"

But, I want to print "mylink1 Thanks mylink2"

What is the proper way to do that?

0

6 Answers 6

3

You can use this function as a drop-in replacement in your code. It uses vsprintf as @h2ooooooo demonstrated. My earlier version failed, because I used the $count parameter of str_replace in the wrong way.

function str_replace_array($search, array $replace, $subject)
{
    return vsprintf(
      str_replace('[Link]', '%s', $subject),
      $replace);
}

$message = "[Link] Thanks [Link]";
echo str_replace_array(
   "[Link]",
   array("mylink1", "mylink2"), 
   $message
);
Sign up to request clarification or add additional context in comments.

2 Comments

This is a neat solution, but you should add an extra str_replace('%', '%%', $subject) to escape % in the message.
And you should replace % with %% in in the replacements if they come from the outside.
3

Perhaps you're searching for sprintf?

$message = "%s Thanks %s";
echo sprintf($message, "mylink1", "mylink2"); // mylink1 Thanks mylink2

DEMO


If you prefer to use an array (useful for dynamic variables), there's vsprintf:

$message = "%s Thanks %s";
echo vsprintf($message, array("mylink1", "mylink2")); // mylink1 Thanks mylink2

DEMO


If you really wish to not use sprintf or vsprintf, you can use preg_replace with the 4th parameter (limit) being "1" (do this only on the first match you find). Make sure you use it with preg_quote so ., +, * etc. has no special meanings:

<?php

function smartReplace($search, $replace, $subject) {
    if (!is_array($search)) {
        throw new Exception('$search must be an array');
    }

    if (!is_array($replace)) {
        throw new Exception('$replace must be an array');
    }

    if (!is_string($subject)) {
        throw new Exception('$subject must be a string');
    }

    for ($i = 0, $len = count($search); $i < $len; $i++) {
        $subject = preg_replace('/' . preg_quote($search[$i], '/') . '/', $replace[$i], $subject, 1);
    }

    return $subject;
}

$message = "[Link] Thanks [Link]";

echo smartReplace(
    array("[Link]", "[Link]"), 
    array("mylink1", "mylink2"), 
    $message
); // mylink1 Thanks mylink2

DEMO

1 Comment

I corrected my answer so it makes use of yours.
0

You can use preg_replace instead of str_replace to set a limit

$message = "[Link] Thanks [Link]";
$replacements = array ("Link 1", "Link 2");
while (!empty($replacements)) {
  $replacement = array_shift($replacements);
  $message = preg_replace("/\[Link\]/", $replacement, $message, 1);
}
echo $message;

Output :

Link 1 Thanks Link 2

2 Comments

Just a side note, while this will work fine in most cases, this will be problematic if the replacement can contain [Link]. While properly not an issue in common cases this could be a potential issue in some special scenarios.
Here is an example: say your using this in an online editor to let users add links to their messages. You run a filter to check that links don't contain XSS (so that your platform does not become a launchpad for payloads). Now the attacker could split the payload over multiple links using [Link] in the payload url and trick your filters that way. This scenario may be a bit constructed, but I think it's just always smart to prevent any potential filter issues in the first place.
0

An easy way would be to combine str_replace and vsprintf.

$message = "[Link] Thanks [Link]";
$template = str_replace("[Link]", "%s", $message);
echo vsprintf($template, array("mylink1", "mylink2"));

Comments

0

try this

$message = "[Link] Thanks [Link]";
echo preg_replace(array("/\[Link\]/", "/\[Link\]/"), 
array("mylink1", "mylink2"), 
$message, 1);

1 Comment

I think it would be more helpful for the OP and further visitors, when you add some explaination to your intention.
0

Using vsprintf could be harmful if you can have % in your message. You could replace all occurrences of % with %% before replacing [Link] with %s and then call vsprintf. But I would just go with simple array functions, that way you don't need to worry about properly escaping characters.

function str_replace_array($message, $search, $replacements)
{
    $result = '';

    $pieces = explode($search, $message);
    $replace = reset($replacements);
    foreach ($pieces as $i => $piece) {
        if ($replace === FALSE) {
            throw new Exception('There are not enough replacements for all occurences of the search string.');
        }
        if ($i !== 0) {
            $result .= $replace;
            $replace = next($replacements);
        }
        $result .= $piece;
    }

    return $result;
}

echo str_replace_array('[Link] Thanks [Link]', '[Link]', array('mylink1', 'mylink2'));

Comments

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.