W3docs

preg_match_all()

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

Introduction

In PHP, regular expressions are essential for searching and manipulating strings. While preg_match() stops at the first match, preg_match_all() keeps scanning and returns every occurrence of a pattern in a string. Use it whenever you need to extract all phone numbers, all tags, all words, or any repeating structure from text.

This article explains the syntax, the all-important $flags argument that controls how results are laid out, and several practical examples.

Syntax

preg_match_all(
    string $pattern,
    string $subject,
    array &$matches = null,
    int $flags = PREG_PATTERN_ORDER,
    int $offset = 0
): int|false
  • $pattern — the regular expression, delimited by /.../ (or any matching delimiters).
  • $subject — the string to search.
  • $matches — an output array (passed by reference) filled with all matches found.
  • $flags — optional. Controls how $matches is structured (see below).
  • $offset — optional. Byte offset in $subject at which to start searching.

It returns the number of full pattern matches (which may be 0), or false if the pattern is invalid.

A simple match

The most basic use is to collect every substring that matches a pattern. Here we pull all numbers out of a sentence:

<?php

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

$count = preg_match_all('/\d+/', $subject, $matches);

echo "Found $count numbers\n";
print_r($matches[0]);

Output:

Found 3 numbers
Array
(
    [0] => 12
    [1] => 3
    [2] => 7
)

When the pattern has no capturing groups, $matches[0] holds the list of full matches.

Choosing a flag: PREG_PATTERN_ORDER vs PREG_SET_ORDER

The $flags argument decides how matches and capturing groups are organized. The two main flags are mutually exclusive:

  • PREG_PATTERN_ORDER (the default) — $matches[0] is all full matches, $matches[1] is all captures of group 1, $matches[2] is all captures of group 2, and so on. Think "column by column."
  • PREG_SET_ORDER$matches[0] is the first complete match (full match + its groups), $matches[1] is the second, and so on. Think "row by row."

You can also add PREG_OFFSET_CAPTURE to record the byte offset of each match alongside its text.

PREG_SET_ORDER (group results by occurrence)

This layout is the easiest to loop over when each match has several capturing groups:

php— editable, runs on the server

Output:

Name: Alice, Age: 25
Name: Bob, Age: 30

With PREG_SET_ORDER, each $match is one occurrence: $match[0] is the full match, $match[1] is the first group (name), $match[2] is the second group (age).

PREG_PATTERN_ORDER (group results by pattern)

The same pattern with the default flag returns the groups as parallel arrays:

<?php

$pattern = '/([A-Z][a-z]+) (\d+)/';
$subject = 'Alice 25 Bob 30';

preg_match_all($pattern, $subject, $matches, PREG_PATTERN_ORDER);

print_r($matches[1]); // all names
print_r($matches[2]); // all ages

Output:

Array
(
    [0] => Alice
    [1] => Bob
)
Array
(
    [0] => 25
    [1] => 30
)

Named capturing groups

Naming groups with (?<name>...) makes the result self-documenting — the names become array keys (alongside the numeric indexes):

<?php

$pattern = '/(?<name>[A-Z][a-z]+) (?<age>\d+)/';
$subject = 'Alice 25 Bob 30';

preg_match_all($pattern, $subject, $matches, PREG_SET_ORDER);

foreach ($matches as $match) {
  echo "{$match['name']} is {$match['age']}\n";
}

Output:

Alice is 25
Bob is 30

Common gotchas

  • Check the return value, not the array. A pattern can match zero times and still succeed; preg_match_all() returns 0, while false means the regex itself was invalid. Use === false to detect errors. See preg_last_error() for the specific failure reason.
  • $matches is overwritten. Each call replaces the previous contents of the output array.
  • Pick the right flag for your loop. Use PREG_SET_ORDER when you want one row per match; use the default PREG_PATTERN_ORDER when you want one column per group.
  • Escape special characters in dynamic patterns with preg_quote() when the pattern comes from user input.

Conclusion

preg_match_all() returns every match of a pattern in a string, making it the go-to function for extracting repeating data. The key to using it well is understanding the $flags argument: PREG_SET_ORDER groups results by occurrence, while the default PREG_PATTERN_ORDER groups them by capturing group.

For related tools, see preg_match() for a single match, preg_replace() for find-and-replace, and preg_split() for splitting strings by a pattern.

Practice

Practice
What is the purpose of the preg_match_all() function in PHP?
What is the purpose of the preg_match_all() function in PHP?
Was this page helpful?