I want a version of strreplace() that only replaces the first match in the target string. Is there an easy solution to this, or do I need a hacky solution?
Can be done with preg_replace:
<?
$str = 'abcdef abcdef abcdef';
// pattern, replacement, string, limit
echo preg_replace('/abc/', '123', $str, 1); // outputs '123def abcdef abcdef'
?>
The magic is in the optional fourth parameter [Limit]. From the documentation:
[Limit] - The maximum possible replacements for each pattern in each subject string. Defaults to -1 (no limit).
The easiest way would be to use regular expression.
The other way is to find the position of the string with strpos() and then an substr_replace()
But i would really go for the RegExp.
There's no version of it, but the solution isn't hacky at all.
$pos = strpos($haystack,$needle);
if ($pos !== false) {
$newstring = substr_replace($haystack,$replace,$pos,strlen($replace));
}
Pretty easy, and saves the performance penalty of regular expressions.
Unfortunately I don't know of any PHP funciton which can do this. You can roll your own fairly easily like this:
function replace_first($find, $replace, $subject) {
// stolen from the comments at PHP.net/str_replace
return implode($replace, explode($find, $subject, 1));
}
The answers by 'zombat' and 'too much php' are unfortunately not correct. This is a revision to the answer zombat posted (as I don't have enough reputation to post a comment):
$pos = strpos($haystack,$needle);
if ($pos !== false) {
$newstring = substr_replace($haystack,$replace,$pos,strlen($needle));
}
Note the strlen($needle), instead of strlen($replace). Zombat's example will only work correctly if needle and replace are the same length.
Here's the same functionality in a function with the same signature as PHP's own str_replace:
function str_replace_first($search, $replace, $subject) {
$pos = strpos($subject, $search);
if ($pos !== false) {
$subject = substr_replace($subject, $replace, $pos, strlen($search));
}
return $subject;
}
This is the revised answer of 'too much php':
implode($replace, explode($search, $subject, 2));
Note the 2 at the end instead of 1. Or in function format:
function str_replace_first($search, $replace, $subject) {
return implode($replace, explode($search, $subject, 2));
}
I timed the two functions and the first one is twice as fast when no match is found. They are the same speed when a match is found.