preg_replace_callback_array
In PHP, regular expressions are an essential tool for manipulating and searching strings. The preg_replace_callback_array() function is one of the many
Introduction
In PHP, regular expressions are an essential tool for matching, searching, and transforming strings. Available since PHP 7.1, the preg_replace_callback_array() function lets you replace all matches of several regular-expression patterns in a single call, where each pattern has its own callback that computes the replacement. It is the array-driven sibling of preg_replace_callback(): instead of passing one pattern and one callback, you pass a map of pattern => callback pairs.
This chapter explains what the function returns, walks through its parameters, and shows runnable examples — including the common gotchas around pattern order and return types.
When to use it
Reach for preg_replace_callback_array() when:
- You need to apply different replacement logic to different patterns in one pass over the subject.
- You'd otherwise chain several
preg_replace_callback()calls — collapsing them keeps the code readable and the intent in one place. - The replacement value can't be expressed as a static string, so plain
preg_replace()won't do — you need to compute it from the matched text.
If you only have a single pattern, use preg_replace_callback(). If the replacements are fixed strings, use preg_replace().
Syntax
preg_replace_callback_array(
array $pattern_and_callbacks,
string|array $subject,
int $limit = -1,
int &$count = null,
int $flags = 0
): string|array|null| Parameter | Description |
|---|---|
$pattern_and_callbacks | An associative array whose keys are regex patterns and whose values are callbacks. Each callback receives the array of matches and returns the replacement string. |
$subject | The string (or array of strings) to search and modify. |
$limit | Maximum replacements per pattern per subject string. The default -1 means no limit. |
&$count | If passed, it is filled with the total number of replacements made (by reference). |
$flags | Optional PREG_OFFSET_CAPTURE and/or PREG_UNMATCHED_AS_NULL, which change the shape of the $matches passed to each callback. |
Return value: if $subject is a string, a string is returned; if $subject is an array, an array is returned. On a regex error it returns null.
Note: Callbacks should return a string. A numeric return value (like an int) is automatically cast to a string. Returning null results in an empty string.
Basic example
The first callback upper-cases every word; the second increments every run of digits. Both patterns are applied to the same subject in one call.
<?php
$patterns_and_callbacks = [
'/[a-z]+/i' => function ($matches) {
return strtoupper($matches[0]);
},
'/\d+/' => function ($matches) {
return (int) $matches[0] + 1;
},
];
$string = 'This is a test string with 1234';
echo preg_replace_callback_array($patterns_and_callbacks, $string);
// THIS IS A TEST STRING WITH 1235Here $matches[0] is the full text matched by the pattern. The second callback returns an integer (1234 + 1), which PHP casts to the string "1235".
Pattern order matters
The patterns are applied in array order, and each one runs on the result of the previous one. This means an earlier callback can change the text a later pattern sees — a common source of surprises.
<?php
$subject = 'abc123';
$result = preg_replace_callback_array([
// Runs first: wraps every digit run in brackets.
'/\d+/' => fn ($m) => '[' . $m[0] . ']',
// Runs second: now sees "abc[123]" and upper-cases the letters.
'/[a-z]+/' => fn ($m) => strtoupper($m[0]),
], $subject);
echo $result;
// ABC[123]If you reordered the two patterns, the letters would be upper-cased before the digit pattern ran — the digit result is the same, but in general the order can change the output.
Counting replacements with $count
Pass a variable as the fourth argument to learn how many replacements happened across all patterns.
<?php
$subject = 'cat dog cat bird cat';
$result = preg_replace_callback_array(
['/cat/' => fn ($m) => 'fish'],
$subject,
-1,
$count
);
echo $result . "\n"; // fish dog fish bird fish
echo "Replacements: $count"; // Replacements: 3Working with an array subject
When $subject is an array, the function processes each element and returns an array of the same shape.
<?php
$subjects = ['Order #12', 'Order #7'];
$result = preg_replace_callback_array(
['/\d+/' => fn ($m) => str_pad($m[0], 4, '0', STR_PAD_LEFT)],
$subjects
);
print_r($result);
// Array
// (
// [0] => Order #0012
// [1] => Order #0007
// )Common pitfalls
- Forgetting delimiters. Keys must be valid regex strings with delimiters, e.g.
'/\d+/', not'\d+'. A missing delimiter makes the call returnnulland emit a warning. - Returning non-strings on purpose. While numeric returns are cast for you, returning arrays or objects triggers a
TypeError. Cast or format your value before returning it. - Assuming patterns are independent. As shown above, each pattern operates on the output of the previous one. Order your map deliberately.
- Using capture groups vs. the full match.
$matches[0]is the whole match;$matches[1],$matches[2], … are the captured groups. Reference the right index for your logic.
Related functions
preg_replace_callback()— single pattern + single callback.preg_replace()— replace with static strings or back-references.preg_match()andpreg_match_all()— find matches without replacing.- PHP callback functions — how callables work in PHP.
Conclusion
preg_replace_callback_array() provides a clean, single-pass way to apply different replacement logic to multiple regex patterns. It shines when each pattern needs its own computed replacement, replacing what would otherwise be several chained preg_replace_callback() calls. Remember that patterns run in array order and that callbacks should return strings, and the function will keep your text-transformation code compact and readable.