preg_replace_array
Replaces each match of a pattern with the next value from an array, in order.
preg_replace_array(string $pattern, array $replacements, string $subject): stringParameters
| Parameter | Type | Description |
|---|---|---|
$$pattern | string | A PCRE pattern, including delimiters, matched against the subject. |
$$replacements | array | Values consumed left to right, one per match; treated as literal strings. |
$$subject | string | The string to perform replacements on. |
Return value
stringThe subject with each match replaced by the next element of the replacements array.
Errors
An invalid pattern makes preg_replace_callback() return null, which then fails the declared string return type with a TypeError.
preg_replace_array() runs preg_replace_callback() and, for every match, shifts the next value off the replacements array. Match one gets element zero, match two gets element one, and so on. What the pattern captured is never consulted — position is the only thing that decides which replacement is used.
When to reach for it
This is the mechanism behind Laravel's translator filling :placeholder tokens, and that is the shape it fits best: a template with several same-shaped slots that must be filled left to right. Use it for building a sentence from an ordered list, substituting values into repeated markers, or numbering repeated tokens.
What trips people up
Running out of replacements does not stop the substitution. array_shift() on an exhausted array returns null, and null is coerced to an empty string — so surplus matches are deleted rather than left in place. Count the matches with preg_match_all() first if the input is not under your control.
The replacements are literal strings, not preg_replace() replacement patterns. $1 or \\1 inside a replacement is inserted verbatim, and a replacement full of regex metacharacters is safe. Extra elements beyond the last match are simply discarded.
Example
When to use it
- Fill ordered :placeholder tokens in a translation-style string.
- Substitute a list of bindings into the question marks of a rendered SQL query.
- Number or wrap each occurrence of a repeated marker in a template.
Frequently asked questions
How do I replace regex matches one by one from an array in PHP?
Use preg_replace_array($pattern, $replacements, $subject), which consumes one array element per match in left-to-right order. Plain preg_replace() cannot do this because it applies the same replacement to every match.
What happens if there are more matches than replacements?
The surplus matches are replaced with an empty string, not left in place, because array_shift() returns null once the array is exhausted. Count the matches with preg_match_all() beforehand when the number of matches is not fixed.
Can I use $1 backreferences in preg_replace_array replacements?
No. The replacements are returned from a callback, so they are inserted literally — $1 or \1 appears in the output as written. That also means replacements containing regex metacharacters or backslashes need no escaping.
More examples
Replacements are literal, not replacement patterns
With preg_replace() every one of these replacements would be mangled — $1 and \1 would be treated as backreferences and the backslash would need escaping. Because preg_replace_array() returns the value from a callback, each replacement is inserted exactly as written, which makes it safe for values you did not author.
<?php
echo preg_replace_array('/\{\}/', ['$1', 'a\1b', 'C:\path'], 'x={} y={} z={}'), "\n";
// x=$1 y=a\1b z=C:\pathOrdered placeholders in a message
Position, not name, decides the mapping — swap two elements of the array and Ada becomes the item. This is why the helper suits generated templates but not hand-edited ones, where a named substitution such as Str::replace() or the translator's own array form is safer.
<?php
$template = 'Hi :name, your :item ships on :date.';
echo preg_replace_array('/:[a-z_]+/', ['Ada', 'keyboard', 'March 3'], $template), "\n";
// Hi Ada, your keyboard ships on March 3.Check the count before you rely on it
The third question mark is replaced with an empty string, leaving a trailing space inside the brackets rather than the original marker. Counting with preg_match_all() first turns a silent data-loss bug into something you can log or reject.
<?php
$subject = 'a ? b ? c ?';
$replacements = ['1', '2'];
$matches = preg_match_all('/\?/', $subject);
if ($matches !== count($replacements)) {
echo "expected {$matches} replacements, got ".count($replacements)."\n";
}
echo '['.preg_replace_array('/\?/', $replacements, $subject)."]\n";
// [a 1 b 2 c ]
Discussion