Str::replaceFirst

Replaces only the first occurrence of a value in a string and leaves later occurrences intact.

Signature
Str::replaceFirst(string $search, string $replace, string $subject): string

Parameters

ParameterTypeDescription
$$searchstringThe value to find. An empty string returns the subject unchanged.
$$replacestringThe replacement text. Pass an empty string to delete the first occurrence.
$$subjectstringThe 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

Try it yourself
Loading editor…
Press Run to execute the code.

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.

Example · php
<?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      => 7f3a

replaceFirst 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.

Example · php
<?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 prefix

Trimming 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().

Example · php
<?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

  • Be the first to comment on this lesson.