Multibyte strings7 min readExamples run on PHP 8.5.10

mb_eregi()

Learn how mb_eregi() tests a string against a case-insensitive multibyte regular expression in PHP 8.4, how it fills $matches, and which mistakes to avoid.

Signature

mb_eregi(string $pattern, string $string, array &$matches = null): bool
Available since PHP 4.2.07.48.08.18.28.38.48.5All versions →

Purpose

mb_eregi() checks whether a regular expression matches a string, ignoring letter case, and it understands multibyte characters. It belongs to the mb_ereg* family, which works with the character encoding set for multibyte regex rather than with raw bytes. That makes it a fit for text such as CAFÉ versus café, where case folding applies to a non-ASCII letter.

The function only reports a match and optionally captures substrings. It does not replace or split anything.

Signature

Parameters and defaults

  • $pattern: the regular expression. Unlike the preg_* functions, it takes no delimiters and no trailing flags. Case-insensitivity is built into the function.
  • $string: the text to search.
  • $matches: optional, passed by reference. When you pass it, PHP fills it with the full match at index 0 and each parenthesized group at indexes 1, 2 and so on. The default is null, which means no captures are stored.

The character encoding used is the internal encoding, or the one set with mb_regex_encoding(). Calling mb_regex_encoding('UTF-8') first makes your intent explicit.

Return value and failure cases

The function returns a bool: true if the pattern matches and false otherwise. When you pass $matches and nothing matches, it is set to an empty array.

Two changelog entries matter when reading older code:

  • Since PHP 8.0.0 the function returns true on success. Before that it returned the byte length of the match (or 1 in some cases) when $matches was given.
  • Since PHP 7.1.0 $matches becomes an empty array when nothing matched. Before that it was left unchanged.

A pattern that the regex engine cannot compile will not produce a meaningful match, so test your patterns with known inputs.

Examples

The first example is a plain case-insensitive test.

Example
<?php
mb_regex_encoding('UTF-8');
var_dump(mb_eregi('hello', 'Say HELLO there'));
Output
bool(true)

The second captures a group that contains a non-ASCII letter. The uppercase É in the subject matches the lowercase é in the pattern.

Example
<?php
mb_regex_encoding('UTF-8');
$found = mb_eregi('caf(é)', 'CAFÉ', $matches);
echo json_encode(['matched' => $found, 'matches' => $matches], JSON_UNESCAPED_UNICODE | JSON_UNESCAPED_SLASHES);
Output
{"matched":true,"matches":["CAFÉ","É"]}

The third shows two behaviors: delimiters are treated as literal characters, and a failed match leaves $matches empty.

Example
<?php
mb_regex_encoding('UTF-8');
$withDelimiters = mb_eregi('/abc/i', 'ABC');
$plain = mb_eregi('abc', 'ABC');
$none = mb_eregi('^x', 'abc', $matches);
echo json_encode(['withDelimiters' => $withDelimiters, 'plain' => $plain, 'none' => $none, 'matches' => $matches], JSON_UNESCAPED_UNICODE | JSON_UNESCAPED_SLASHES);
Output
{"withDelimiters":false,"plain":true,"none":false,"matches":[]}

Edge cases

  • Anchors: ^ and $ work as you would expect, so mb_eregi('^x', 'abc') is false.
  • Unmatched input: with $matches supplied, you always get an array back, empty on failure. Check the boolean result rather than inspecting the array alone.
  • Encoding mismatch: if the string is not valid in the active regex encoding, results can be unreliable. Keep your data and mb_regex_encoding() consistent.
  • Syntax flavor: the pattern syntax comes from the multibyte regex engine, not PCRE. Do not assume every preg_match() feature, such as inline flags or delimiters, carries over.

Common mistakes

  1. Adding delimiters or flags such as /abc/i. They are matched literally, so the match usually fails.
  2. Expecting a length or an integer. Code written for PHP 7 may compare the result with a byte count. In PHP 8 the result is only true or false.
  3. Reading $matches without checking success. On failure it is an empty array, so $matches[1] does not exist.
  4. Forgetting the encoding. Set mb_regex_encoding() when your application does not already guarantee it.
  5. Using it for simple substring tests. A plain search is clearer when you do not need a regular expression.
  • mb_ereg(): the case-sensitive counterpart.
  • mb_regex_encoding(): gets or sets the encoding for multibyte regex functions.
  • preg_match(): the PCRE-based alternative, which uses delimiters and flags.

Recap

mb_eregi() returns true when a delimiter-free pattern matches a string regardless of case, with multibyte awareness. Pass $matches to receive the full match and captured groups. It is an empty array when nothing matches. In PHP 8 the result is always a boolean.

Tested examples

Basic case-insensitive match
<?php
mb_regex_encoding('UTF-8');
var_dump(mb_eregi('hello', 'Say HELLO there'));
Output
bool(true)
Capturing a non-ASCII letter
<?php
mb_regex_encoding('UTF-8');
$found = mb_eregi('caf(é)', 'CAFÉ', $matches);
echo json_encode(['matched' => $found, 'matches' => $matches], JSON_UNESCAPED_UNICODE | JSON_UNESCAPED_SLASHES);
Output
{"matched":true,"matches":["CAFÉ","É"]}
Delimiters are literal and failed matches give an empty array
<?php
mb_regex_encoding('UTF-8');
$withDelimiters = mb_eregi('/abc/i', 'ABC');
$plain = mb_eregi('abc', 'ABC');
$none = mb_eregi('^x', 'abc', $matches);
echo json_encode(['withDelimiters' => $withDelimiters, 'plain' => $plain, 'none' => $none, 'matches' => $matches], JSON_UNESCAPED_UNICODE | JSON_UNESCAPED_SLASHES);
Output
{"withDelimiters":false,"plain":true,"none":false,"matches":[]}