$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?
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
);
str_replace('%', '%%', $subject) to escape % in the message.% with %% in in the replacements if they come from the outside.Perhaps you're searching for sprintf?
$message = "%s Thanks %s";
echo sprintf($message, "mylink1", "mylink2"); // mylink1 Thanks mylink2
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
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
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
[Link]. While properly not an issue in common cases this could be a potential issue in some special scenarios.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.try this
$message = "[Link] Thanks [Link]";
echo preg_replace(array("/\[Link\]/", "/\[Link\]/"),
array("mylink1", "mylink2"),
$message, 1);
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'));