W3docs

preg_replace_callback

In PHP, regular expressions are an essential tool for manipulating and searching strings. The preg_replace_callback() function is one of the many functions that

Introduction

preg_replace_callback() performs a regular-expression search-and-replace, but instead of supplying a fixed replacement string, you hand it a callback function that is run for each match. The callback receives the match (and any capturing groups) and returns the text to substitute in. This lets you compute replacements with real PHP logic — uppercase a word, add 1 to a number, look a value up in a table — which the plain preg_replace() function cannot do.

Use it whenever the replacement depends on what was matched. If your replacement is a constant or a simple backreference like $1, reach for preg_replace() instead; if you need a different callback per pattern, see preg_replace_callback_array().

Syntax

preg_replace_callback(
    string|array $pattern,
    callable $callback,
    string|array $subject,
    int $limit = -1,
    int &$count = null,
    int $flags = 0
): string|array|null
ParameterDescription
$patternThe regular expression (a delimited string) to match, or an array of patterns.
$callbackA callable run for each match. It receives the matches array and returns the replacement string.
$subjectThe string (or array of strings) to search and modify.
$limitMaximum replacements per subject string. -1 (the default) means no limit.
$countPassed by reference; filled with the number of replacements made.
$flagsPREG_OFFSET_CAPTURE and/or PREG_UNMATCHED_AS_NULL, mirroring preg_match().

It returns the modified subject, or null if a regex error occurs. The first argument to the callback is the $matches array: $matches[0] is the whole match and $matches[1], $matches[2], … are the captured groups — exactly like the array preg_match() fills in.

Basic example: uppercase every word

php— editable, runs on the server

The pattern \w+ matches each run of word characters. For every match the callback receives $matches[0] (the word) and returns its uppercase form, which is spliced back into the string.

Working with capturing groups

Parentheses in the pattern create capturing groups that show up at $matches[1], $matches[2], and so on. Here we add one to every number in a string:

<?php

$subject = 'Room 12, floor 3, building 7';

$result = preg_replace_callback('/(\d+)/', function ($m) {
    return (string) ((int) $m[1] + 1);
}, $subject);

echo $result;
// Room 13, floor 4, building 8

Because the callback runs real code, the increment is computed per match — something a static replacement string can never express.

A practical use case: masking sensitive data

A common job is partially hiding emails or card numbers in logs. The callback can decide how much of each match to reveal:

<?php

$text = 'Contact: [email protected] or [email protected]';

$result = preg_replace_callback('/([\w.]+)@([\w.]+)/', function ($m) {
    $name = $m[1];
    $masked = $name[0] . str_repeat('*', max(strlen($name) - 1, 1));
    return $masked . '@' . $m[2];
}, $text);

echo $result;
// Contact: a****@example.com or b**@test.org

Counting and limiting replacements

The $limit and $count parameters let you cap how many matches are processed and learn how many actually were:

<?php

$subject = 'a a a a a';

$result = preg_replace_callback('/a/', function ($m) {
    return 'b';
}, $subject, 2, $count);

echo $result, "\n"; // b b a a a
echo $count;        // 2

Only the first two as are replaced because $limit is 2, and $count reports the number of replacements made.

preg_replace vs. preg_replace_callback

UseFunction
Fixed text or a backreference like $1preg_replace()
Replacement computed from the matchpreg_replace_callback()
A different callback per patternpreg_replace_callback_array()

For matching without replacing, see preg_match() and preg_match_all(), and the PHP regular expressions chapter for pattern syntax.

Common gotchas

  • Always return a string. The callback's return value is cast to a string and inserted. Returning null removes the match; forgetting to return inserts an empty string.
  • Reference the right index. $matches[0] is the full match; group 1 lives at $matches[1]. Off-by-one here is the most frequent bug.
  • Escape with care. Unlike preg_replace(), you do not write $1/\1 backreferences in the result — you build the string yourself, so there is nothing to escape in the replacement.
  • A null return value from the function itself (not the callback) signals a regex error, such as an unmatched delimiter.

Conclusion

preg_replace_callback() is the right tool whenever a replacement must be computed rather than stated. It pairs the matching power of regular expressions with arbitrary PHP logic in the callback, making it ideal for transforming, masking, or recalculating matched text. For static replacements stick with preg_replace(), and for several patterns at once use preg_replace_callback_array().

Practice

Practice
What is the preg_replace_callback() function in PHP?
What is the preg_replace_callback() function in PHP?
Was this page helpful?