Modify Strings
Modifying a string means producing a changed version of it: replacing words, inserting or removing characters, masking sensitive data, filling templates, or normalizing format. PHP provides several fu
Modifying a string means producing a changed version of it: replacing words, inserting or removing characters, masking sensitive data, filling templates, or normalizing format. PHP provides several functions for this, each suited to a different kind of change.
| Task | Function |
|---|---|
| Replace every occurrence of some text | str_replace() |
| Same, ignoring case | str_ireplace() |
| Replace several values at once without re-replacing | strtr() |
| Replace or insert text at a specific position | substr_replace() |
| Replace text matching a pattern | preg_replace() |
| Change case, trim, pad | strtolower(), trim(), str_pad() (see String Functions) |
One rule applies to all of them: they return a new string and leave the original unchanged. Always assign the result.
<?php
$text = "Hello World";
str_replace("World", "PHP", $text); // result discarded
echo $text . "\n"; // Hello World
$text = str_replace("World", "PHP", $text);
echo $text . "\n"; // Hello PHP
str_replace() — Replace Text
What It Does
str_replace() finds every occurrence of a search string and replaces it with a replacement string. It is case-sensitive and does not use patterns — it matches the exact text.
Syntax
str_replace(
array|string $search,
array|string $replace,
string|array $subject,
int &$count = null
): string|array
| Parameter | Meaning |
|---|---|
$search | The text to look for (or an array of texts) |
$replace | The replacement text (or an array of replacements) |
$subject | The string to search in (or an array of strings) |
$count | Optional. Receives the number of replacements made |
Simple Example
<?php
$sentence = "I like cats. Cats are calm. My cat sleeps a lot.";
echo str_replace("cat", "dog", $sentence);
Output
I like dogs. Cats are calm. My dog sleeps a lot.
How It Works
- Every occurrence is replaced, not just the first.
- The search is case-sensitive:
Cats(capital C) is not matched. - It matches text inside other words too:
catsbecomesdogsbecausecatis part ofcats.str_replace()has no concept of "whole words"; for word boundaries, usepreg_replace()with\b(covered in the RegEx lessons).
Counting Replacements
<?php
$text = "The cat chased another cat";
$result = str_replace("cat", "dog", $text, $count);
echo $result . "\n";
echo "Replacements made: $count\n";
Output
The dog chased another dog
Replacements made: 2
The fourth argument is passed by reference: str_replace() writes the number of replacements into $count. This is useful for logging, validation ("did anything change?"), or reporting results to users.
Replacing Several Values at Once
Arrays for Search and Replace
When $search and $replace are arrays, each search item is replaced by the item at the same position in the replacement array.
<?php
$template = "Hi NAME, your plan PLAN expires on DATE.";
$search = ["NAME", "PLAN", "DATE"];
$replace = ["Deepa", "Pro", "31 Dec 2026"];
echo str_replace($search, $replace, $template);
Output
Hi Deepa, your plan Pro expires on 31 Dec 2026.
Fewer Replacements Than Search Items
If the replacement array is shorter, the extra search items are replaced with an empty string:
<?php
echo str_replace(["a", "e", "i"], ["4", "3"], "radio wire") . "\n";
Output
r4do wr3
a → 4, e → 3, and i has no matching replacement, so it is removed.
One Replacement for Many Search Items
If $replace is a single string, it is used for every search item:
<?php
$phone = "(044) 2345-6789";
echo str_replace(["(", ")", " ", "-"], "", $phone);
Output
04423456789
This is a simple way to strip a fixed set of characters. For "remove everything that is not a digit", a regular expression is more complete (shown later in this lesson).
Replacing in Many Strings
If $subject is an array, the replacement is applied to every element and an array is returned:
<?php
$filenames = ["report 2026.pdf", "invoice 0042.pdf", "summary final.pdf"];
print_r(str_replace(" ", "_", $filenames));
Output
Array
(
[0] => report_2026.pdf
[1] => invoice_0042.pdf
[2] => summary_final.pdf
)
The Sequential Replacement Trap
When str_replace() receives arrays, it performs the replacements one after another on the result of the previous step. A later replacement can therefore change text produced by an earlier one.
Example
<?php
// Goal: swap "a" and "b"
echo str_replace(["a", "b"], ["b", "a"], "ab") . "\n";
Output
aa
Why This Happens
- First pass: replace
awithb→"bb". - Second pass: replace
bwitha→"aa".
The b created in the first pass is replaced again in the second pass. The intended swap ("ba") is never produced.
The Fix: strtr()
<?php
echo strtr("ab", ["a" => "b", "b" => "a"]) . "\n";
Output
ba
strtr() scans the original string once, and text that has already been replaced is never replaced again. This is the correct choice whenever replacements might interact with each other.
strtr() — Translate Characters or Substrings
strtr() has two forms.
Form 1: Character-by-Character Translation
strtr(string $string, string $from, string $to): string
Each character in $from is replaced with the character at the same position in $to.
<?php
echo strtr("Hello World", "eo", "30") . "\n";
echo strtr("2026/10/08", "/", "-") . "\n";
Output
H3ll0 W0rld
2026-10-08
e becomes 3 and o becomes 0. This form works on single bytes, so it is not suitable for multibyte characters.
Form 2: Substring Replacement With an Array
strtr(string $string, array $replace_pairs): string
Keys are searched for and replaced with their values.
<?php
$template = "Dear {name}, your order #{order} ships on {date}.";
echo strtr($template, [
'{name}' => 'Anitha',
'{order}' => '1042',
'{date}' => '12 Oct',
]);
Output
Dear Anitha, your order #1042 ships on 12 Oct.
How the Array Form Works
- The original string is scanned once from left to right.
- At each position, the longest matching key is used. If both
"ab"and"abc"are keys,"abc"wins when it matches. - Replaced text is not scanned again, so a value containing
{date}would not be replaced a second time.
These properties make strtr() the safest built-in choice for simple template placeholders, such as email and SMS templates.
Security note: When the result is HTML, escape user-provided values before inserting them:
'{name}' => htmlspecialchars($name). A template function does not make values safe on its own.
str_ireplace() — Case-Insensitive Replacement
<?php
$text = "PHP is great. php is fast. Php is everywhere.";
echo str_ireplace("php", "PHP", $text);
Output
PHP is great. PHP is fast. PHP is everywhere.
str_ireplace() works like str_replace() but ignores letter case when searching. It is useful for normalizing inconsistently written terms or brand names. Case-insensitivity applies to ASCII letters.
substr_replace() — Replace at a Position
What It Does
substr_replace() replaces part of a string identified by position and length, rather than by matching text. It can also insert or delete.
Syntax
substr_replace(
array|string $string,
array|string $replace,
array|int $offset,
array|int|null $length = null
): string|array
| Parameter | Meaning |
|---|---|
$offset | Position to start (0-based). Negative values count from the end. |
$length | How many bytes to replace. null (default) means "to the end". 0 means insert without removing anything. Negative values stop that many bytes before the end. |
Examples
<?php
$text = "Hello World";
echo substr_replace($text, "PHP", 6, 5) . "\n"; // replace
echo substr_replace($text, "Dear ", 6, 0) . "\n"; // insert
echo substr_replace($text, "", 5) . "\n"; // delete to end
echo substr_replace($text, "!", -1, 1) . "\n"; // replace last char
Output
Hello PHP
Hello Dear World
Hello
Hello Worl!
How Each Call Works
- Start at position
6(W), remove5bytes (World), insertPHP. - Start at position
6, remove0bytes, insertDear— a pure insertion. - Start at position
5, no length, replacement""— everything from position 5 onward is deleted. - Offset
-1is the last byte (d), which is replaced with!.
Practical Use: Masking Sensitive Data
<?php
$cardNumber = "4111111111111111";
$phone = "9876543210";
$maskedCard = str_repeat("*", strlen($cardNumber) - 4) . substr($cardNumber, -4);
$maskedPhone = substr_replace($phone, "******", 2, 6);
echo $maskedCard . "\n";
echo $maskedPhone . "\n";
Output
************1111
98******10
- The card number keeps only the last four digits, which is the common standard for showing card numbers on receipts and account pages.
- The phone number keeps the first two and last two digits;
substr_replace()overwrites the six digits in between.
Masking is a display measure. Sensitive data should still be protected in storage and logs; full card numbers should never be stored by your application at all — payment providers handle them.
Note:
substr_replace()counts bytes. For text with multibyte characters, build the result withmb_substr()instead, as inmb_substr($s, 0, 2) . "***" . mb_substr($s, -2).
preg_replace() — Pattern-Based Replacement
When the text to replace is not a fixed string but a pattern — "any digits", "repeated spaces", "anything that is not a letter" — use preg_replace() with a regular expression.
<?php
$phone = "+91 98765-43210";
$comment = "Too many spaces here";
echo preg_replace('/\D+/', '', $phone) . "\n";
echo preg_replace('/\s+/', ' ', $comment) . "\n";
Output
919876543210
Too many spaces here
\D+matches one or more non-digit characters; replacing them with''leaves only digits.\s+matches one or more whitespace characters; replacing them with a single space collapses repeated spaces.
Regular expressions are powerful but harder to read and slower than plain string functions. Prefer str_replace() or strtr() when the text is fixed, and use preg_replace() when you genuinely need patterns. Regular expressions are covered in the PHP RegEx section.
Modifying Individual Characters
A single byte can be changed by assigning to an offset:
<?php
$code = "abc-123";
$code[3] = "_";
echo $code;
Output
abc_123
This is only suitable for single-byte (ASCII) characters. For anything else, use the functions above.
Choosing the Right Function
| Situation | Best Choice | Why |
|---|---|---|
| Replace one fixed text with another | str_replace() | Simple, fast, replaces all occurrences |
| Replace ignoring case | str_ireplace() | Case-insensitive matching |
| Fill a template with several placeholders | strtr() with an array | Single pass, no double replacement |
| Swap or map characters | strtr() | Replacements cannot interfere with each other |
| Change text at a known position (masking, inserting) | substr_replace() | Position-based instead of text-based |
| Replace a pattern (digits, whitespace runs, words) | preg_replace() | Regular expressions describe patterns |
Are These Functions Safe With UTF-8?
str_replace(), str_ireplace() (for ASCII letters), and strtr() with an array match complete byte sequences. When both the search text and the subject are valid UTF-8, a match always corresponds to whole characters, so replacing "₹" or Tamil words works correctly. Position-based functions such as substr_replace() and the character form of strtr() count bytes and are not multibyte-safe.
Practical Example: Creating URL Slugs
A slug is the URL-friendly part of a page address, such as php-and-mysql-the-complete-guide in /blog/php-and-mysql-the-complete-guide.
<?php
function slugify(string $text): string
{
$text = mb_strtolower(trim($text));
$text = strtr($text, [
'&' => ' and ',
'+' => ' plus ',
]);
$text = preg_replace('/[^a-z0-9]+/', '-', $text);
return trim($text, '-');
}
echo slugify(" PHP & MySQL: The Complete Guide! ") . "\n";
echo slugify("C++ for Beginners") . "\n";
Output
php-and-mysql-the-complete-guide
c-plus-plus-for-beginners
Step-by-Step Explanation
trim()removes outer whitespace, andmb_strtolower()lowercases the text.strtr()converts meaningful symbols into words before they are removed. Without this step,C++would become justc.preg_replace('/[^a-z0-9]+/', '-', ...)replaces every run of characters that are not lowercase letters or digits — spaces, punctuation, colons — with a single hyphen.trim($text, '-')removes hyphens left at the start or end (from the trailing!, for example).
Characters outside a–z (such as é or Tamil letters) are removed by step 3. For multilingual sites, convert text to ASCII first using the Transliterator class from the intl extension, or keep Unicode slugs by allowing letters with a Unicode-aware pattern.
Common Mistakes
Not Assigning the Result
Effect: The original string appears unchanged.
Fix: $text = str_replace(...);
Expecting Whole-Word Matching
Effect: Replacing cat also changes category and concatenate.
Fix: Use preg_replace('/\bcat\b/', 'dog', $text).
Sequential Replacements Interfering
Effect: Swaps and overlapping replacements produce wrong results.
Fix: Use strtr() with an array.
Mismatched Search and Replace Arrays
Effect: Extra search items are deleted instead of replaced.
Fix: Keep both arrays the same length, or use an associative array with strtr() so each pair stays together.
Using substr_replace() on Multibyte Text
Effect: Characters are cut in the middle of their byte sequences.
Fix: Build the result with mb_substr().
Inserting Unescaped User Data Into HTML Templates
Effect: Cross-site scripting.
Fix: Escape each value with htmlspecialchars() before replacement.
Best Practices
- Use plain string functions for fixed text and reserve regular expressions for patterns.
- Use
strtr()for templates and mappings where replacements must not affect each other. - Use the
$countargument ofstr_replace()when you need to know whether anything changed. - Keep masking and formatting for display; never treat them as data protection.
- Remember which functions count bytes, and use
mb_*functions for position-based work on international text.
Official reference: https://www.php.net/manual/en/function.str-replace.php