Signature
substr_replace(array|string $string, array|string $replace, array|int $offset, array|int|null $length = null): string|arrayPurpose
substr_replace() swaps out a slice of a string for new text. You pick the slice with a starting position (offset) and an optional length. The function returns a modified copy and never changes the original variable. With the right arguments it can replace, insert or delete text, which makes it handy for masking values, patching fixed-width records and trimming known segments.
Signature
Parameters and defaults
$string: the input. It can be a string, or an array of strings that are processed one at a time.$replace: the text to put in. With array input, it may be one string for all entries or an array with one replacement per entry.$offset: where replacement starts. A non-negative number counts from the beginning. A negative number counts back from the end.$length: how much of the original to replace. It defaults tonull, which means "to the end of the string". A positive number is a count of bytes to replace. A negative number says how many characters to leave untouched at the end. Zero means nothing is removed, so the function inserts$replaceat$offset.
Return value and failure cases
The function returns a string when $string is a string, and an array when $string is an array. It does not return false for out-of-range positions; it clamps them instead. Type problems are the main failure: for example, passing an array for $offset while $string is a single string is rejected with a TypeError in PHP 8.
Since PHP 8.0 $length is explicitly nullable, so passing null is the same as leaving it out.
Example 1: masking part of a value
A fixed offset and length replace a known middle section. A negative offset with no length replaces the tail.
$card = '4111111111111111';
echo substr_replace($card, '********', 4, 8), "\n";
echo substr_replace($card, '****', -4), "\n";4111********1111 411111111111****
Example 2: insert, delete and negative length
A length of 0 inserts. An empty replacement deletes. A negative length stops the replaced region before the end of the string.
$text = 'Hello World';
echo substr_replace($text, 'Big ', 6, 0), "\n";
echo substr_replace($text, '', 5, 6), "\n";
echo substr_replace($text, 'PHP', 6, -2), "\n";Hello Big World Hello Hello PHPld
In the last call, the replaced region begins at index 6 and ends two characters before the end, so Wor becomes PHP and the trailing ld stays.
Example 3: working on an array
When the first argument is an array, each entry is handled in turn. The other arguments can be scalars applied to every entry, or arrays matched by position.
$input = ['A: XXX', 'B: XXX', 'C: XXX'];
$replace = ['AAA', 'BBB', 'CCC'];
$length = [1, 2, 3];
echo json_encode(substr_replace($input, 'YYY', 3, 3)), "\n";
echo json_encode(substr_replace($input, $replace, 3, $length)), "\n";["A: YYY","B: YYY","C: YYY"] ["A: AAAXX","B: BBBX","C: CCC"]
The second call uses a different length for each entry, so the first string keeps two X characters and the second keeps one.
Edge cases
- Offsets outside the string are clamped. An offset past the end appends the replacement. A negative offset reaching before the start behaves like
0. - Bytes, not characters. The function is binary-safe and works on bytes. For UTF-8 text containing multibyte characters, a byte offset can cut a character in half and produce invalid UTF-8. Choose offsets carefully, or use multibyte-aware code when the data is not ASCII.
- Omitted length replaces everything after the offset. This surprises people who expected only a single character to change.
- Negative length is not a count to replace. It is the number of characters preserved at the end.
- Array input with short replacement arrays. When
$replaceis an array with fewer items than the input, the missing entries are treated as empty replacements, so those slices are effectively deleted. Supply one replacement per entry to avoid this.
Common mistakes
- Expecting the original to change. The function returns a new value; assign it back if you want to keep it.
- Forgetting the length when inserting.
substr_replace($s, 'x', 3)truncates the rest of the string. Usesubstr_replace($s, 'x', 3, 0)to insert. - Mixing up positive and negative length. Positive means how many to replace; negative means where to stop relative to the end.
- Using it for search-and-replace. The function does not look for text. It only works with positions. To replace matching text, use
str_replace(). - Applying byte offsets to multibyte text and assuming each offset is one visible character.
Related functions
str_replace()replaces every occurrence of a search string with another string.substr()returns a portion of a string using the same offset and length rules.- String access by index lets you read or change a single character in a string variable.
Recap
Use substr_replace() when you know where in a string a change should happen. The offset chooses the start, length chooses how much is removed, 0 makes an insertion and an empty replacement makes a deletion. It returns a copy, works on bytes, supports array input, and clamps offsets that fall outside the string.
Tested examples
$card = '4111111111111111';
echo substr_replace($card, '********', 4, 8), "\n";
echo substr_replace($card, '****', -4), "\n";
4111********1111 411111111111****
$text = 'Hello World';
echo substr_replace($text, 'Big ', 6, 0), "\n";
echo substr_replace($text, '', 5, 6), "\n";
echo substr_replace($text, 'PHP', 6, -2), "\n";
Hello Big World Hello Hello PHPld
$input = ['A: XXX', 'B: XXX', 'C: XXX'];
$replace = ['AAA', 'BBB', 'CCC'];
$length = [1, 2, 3];
echo json_encode(substr_replace($input, 'YYY', 3, 3)), "\n";
echo json_encode(substr_replace($input, $replace, 3, $length)), "\n";
["A: YYY","B: YYY","C: YYY"] ["A: AAAXX","B: BBBX","C: CCC"]