Str::replaceFirst
Replaces only the first occurrence of a value in a string and leaves later occurrences intact.
Str::replaceFirst(string $search, string $replace, string $subject): stringParameters
| Parameter | Type | Description |
|---|---|---|
$$search | string | The value to find. An empty string returns the subject unchanged. |
$$replace | string | The replacement text. Pass an empty string to delete the first occurrence. |
$$subject | string | The string to search in. |
Return value
stringThe subject with its first occurrence of $search replaced, or the subject unchanged when there is no match.
Str::replaceFirst exists because str_replace has no limit argument. It locates the leftmost occurrence with strpos, splices the replacement in with substr_replace, and returns the subject untouched if there is no match — no exception, no false, no warning.
When you actually want it
Almost always when the position carries meaning: stripping a leading slash, removing a base path from an absolute path, dropping a prefix like Bearer from a header, or rewriting the first delimiter in a line. Reaching for it as a general replace is a smell — if every occurrence should change, use Str::replace.
For a prefix specifically, Str::replaceStart is stricter: it only replaces when the string genuinely begins with the search, whereas replaceFirst will happily rewrite a match found in the middle of a string that has no prefix at all.
Always case-sensitive
There is no flag here, unlike Str::replace and Str::remove. Lowercase both sides yourself if you need loose matching, or use Str::replaceMatches with a case-insensitive pattern.
Byte offsets
The lookup uses byte functions, which is safe for UTF-8 because a valid multibyte sequence can only match on a character boundary. The returned string stays valid.
Example
When to use it
- Strip a leading slash or a base directory from a path without touching later separators.
- Remove a 'Bearer ' prefix from an Authorization header value.
- Rewrite the first delimiter in a line to split a key from a value that also contains the delimiter.
Frequently asked questions
How do I replace only the first occurrence of a string in PHP?
Use Str::replaceFirst($search, $replace, $subject), since str_replace has no limit argument. It splices the replacement in at the leftmost match and returns the subject untouched when there is no match.
What is the difference between Str::replaceFirst and Str::replaceStart?
replaceStart only acts when the string actually begins with the search value, while replaceFirst rewrites the leftmost match wherever it is. Use replaceStart to strip a prefix so a string without that prefix is left alone.
Is Str::replaceFirst case-insensitive?
No, and unlike Str::replace and Str::remove it has no flag to change that. Normalise both sides with Str::lower first, or use Str::replaceMatches with a pattern carrying the i modifier.
More examples
Splitting on the first delimiter only
The first header's value contains its own ': ', so a plain explode would have produced three parts and dropped data. Replacing only the first occurrence turns a positional rule into something explode can act on safely.
<?php
use Illuminate\Support\Str;
$lines = [
'Authorization: Bearer abc: def',
'X-Trace-Id: 7f3a',
];
foreach ($lines as $line) {
// Mark the first colon, then split on the marker.
[$name, $value] = explode("\0", Str::replaceFirst(': ', "\0", $line), 2);
echo str_pad($name, 16), '=> ', $value, "\n";
}
// Authorization => Bearer abc: def
// X-Trace-Id => 7f3areplaceFirst versus replaceStart
The two agree on the first path and diverge on the second. When you mean 'strip this prefix', replaceStart says so and cannot damage a string that lacks the prefix; replaceFirst will reach into the middle.
<?php
use Illuminate\Support\Str;
$path = 'var/www/app/var/cache';
// Finds the leftmost match anywhere in the string.
echo Str::replaceFirst('var/', '', $path), "\n";
// www/app/var/cache
// Only acts when the string actually starts with the search.
echo Str::replaceStart('var/', '', $path), "\n";
// www/app/var/cache
$other = 'srv/var/www';
echo Str::replaceFirst('var/', '', $other), "\n";
// srv/www <-- rewrote a match in the middle
echo Str::replaceStart('var/', '', $other), "\n";
// srv/var/www <-- left alone, no prefixTrimming a base path in an application
Only the first occurrence is removed, so the second 'app' segment in the path survives — a global replace would have mangled it. Requires a booted application for base_path().
<?php
namespace App\Support;
use Illuminate\Support\Str;
class RelativePath
{
public static function from(string $absolute): string
{
// base_path() returns something like /var/www/app
return ltrim(
Str::replaceFirst(base_path(), '', $absolute),
DIRECTORY_SEPARATOR
);
}
}
// RelativePath::from('/var/www/app/app/Models/User.php')
// => 'app/Models/User.php'
Discussion