Regular expressions
A regular expression is a pattern for searching text. It checks whether a string looks like a phone number or an email, pulls numbers out of text, replaces fragments by a rule. In PHP patterns are handled by functions whose names start with preg_.
Matching a pattern
preg_match() returns 1 if the pattern is found and 0 if not. The pattern is written between slashes:
<?php
echo preg_match('/cat/', 'My cat sleeps'), "\n"; // 1
echo preg_match('/dog/', 'My cat sleeps'); // 0The letter u after the pattern enables Unicode support, i makes the search case-insensitive: /cat/ui.
Notation
| Form | What it means |
|---|---|
\d | A digit |
\w | A letter, a digit or an underscore |
\s | A whitespace character |
. | Any character |
[abc] | One of the listed characters |
+ | One or more times |
* | Zero or more times |
? | Zero or one time |
{3} | Exactly three times |
^ and $ | The start and end of the string |
Checking a format
The ^ and $ signs require the whole string to match the pattern, not just a part of it:
<?php
$pattern = '/^\d{4}-\d{2}-\d{2}$/';
echo preg_match($pattern, '2025-01-30'), "\n"; // 1
echo preg_match($pattern, '30.01.2025'); // 0Groups
A part of the pattern in parentheses is a group. The matched groups go into the array passed as the third argument:
<?php
preg_match('/(\d+) USD/', 'Price: 250 USD.', $matches);
echo $matches[0], "\n"; // 250 USD
echo $matches[1]; // 250The element at index 0 is the whole match, followed by the groups in order.
Every match
preg_match_all() finds all the matches rather than the first one:
<?php
preg_match_all('/\d+/', 'Order 15, items 3, total 4200', $matches);
echo implode(', ', $matches[0]); // 15, 3, 4200Replacing
preg_replace() replaces everything that matched the pattern:
<?php
echo preg_replace('/\s+/', ' ', 'too many spaces'), "\n";
echo preg_replace('/\D/', '', '+1 (555) 123-45-67');The first line turns runs of spaces into a single space, the second leaves only the digits of the phone number: 15551234567.
Splitting
preg_split() splits a string by a pattern — for when there is more than one separator:
<?php
$parts = preg_split('/[,;]\s*/', 'tea, coffee; juice');
echo count($parts), ' ', $parts[2]; // 3 juiceCommon mistake
Do not write complex patterns where a ready-made check exists. An email address or a URL is more reliably checked with filter_var():
<?php
var_dump(filter_var('anna@example.com', FILTER_VALIDATE_EMAIL) !== false); // bool(true)
var_dump(filter_var('not an email', FILTER_VALIDATE_EMAIL) !== false); // bool(false)And for a plain substring search str_contains() is enough — it is faster and clearer.