Signature
mb_ord(string $string, ?string $encoding = null): int|falsePurpose
mb_ord() answers the question "which Unicode code point is the first character of this string?" It reads the string in a given character encoding, decodes the first character and returns its numeric value. The letter A gives 65, the euro sign gives 8364, and the elephant emoji gives 128024.
This is different from ord(), which only looks at the first byte. In UTF-8 many characters take two, three or four bytes, so a byte value says little about the character itself. mb_ord() is the multibyte-aware counterpart and it complements mb_chr(), which goes in the opposite direction.
Signature
Parameters and defaults
$string: the text to inspect. Only its first character matters; the rest is ignored.$encoding: the character encoding of$string, such as"UTF-8","ISO-8859-1"or"Windows-1252". If you omit it or passnull, PHP uses the current internal encoding, which you can read withmb_internal_encoding().
Passing the encoding explicitly keeps your code independent of configuration, so it is a good habit.
Return value and failure cases
On success you get an int: the Unicode code point of the first character. On failure the function returns false, so a strict comparison with false is the correct way to detect a problem.
Since PHP 8.0.0, an invalid $encoding name throws a ValueError. Before 8.0.0 it emitted a warning and returned false. Also since 8.0.0, the $encoding parameter is nullable.
Example 1: Basic code points
The following example decodes four characters of increasing byte length. Unicode escapes keep the source file unambiguous.
$values = [
mb_ord("A", "UTF-8"),
mb_ord("\u{E9}", "UTF-8"),
mb_ord("\u{20AC}", "UTF-8"),
mb_ord("\u{1F418}", "UTF-8"),
];
echo json_encode($values), "\n";[65,233,8364,128024]
The values are 65, 233, 8364 and 128024. They are the code points U+0041, U+00E9, U+20AC and U+1F418.
Example 2: Only the first character counts
The next example compares mb_ord() with ord() on a string that starts with a three-byte character.
$text = "\u{20AC}uro";
echo json_encode([
'mb_ord' => mb_ord($text, 'UTF-8'),
'ord' => ord($text[0]),
'bytes' => strlen("\u{20AC}"),
]), "\n";{"mb_ord":8364,"ord":226,"bytes":3}
mb_ord() returns the code point 8364 for the whole euro sign. ord() returns 226, which is merely the first of its three UTF-8 bytes. The example passes $text[0], the first byte, because calling ord() with a longer string is deprecated as of PHP 8.5. The trailing letters uro are ignored by both functions.
Example 3: Encoding changes the meaning
The same raw byte can be a different character in a different encoding. Byte 0x80 is a control character in ISO-8859-1 but the euro sign in Windows-1252. An unknown encoding name raises a ValueError.
echo json_encode([
mb_ord("\x80", "ISO-8859-1"),
mb_ord("\x80", "Windows-1252"),
]), "\n";
try {
mb_ord("A", "NOPE");
} catch (ValueError $e) {
echo get_class($e), "\n";
}[128,8364] ValueError
Edge cases
- Emoji and characters outside the Basic Multilingual Plane return a single large integer, not a surrogate pair, so values above 65535 are normal.
- Combining sequences: a letter followed by a combining accent is two code points.
mb_ord()reports only the first one, so it does not describe a whole user-perceived character (grapheme). - Empty strings do not have a first character, so check the input before calling the function rather than relying on a particular result.
- Malformed input may lead to a
falsereturn. Always compare strictly withfalse, because a valid code point is neverfalsebut a loose check against0could still confuse you.
Common mistakes
- Using
ord()for non-ASCII text and expecting a code point. It returns a byte value from 0 to 255. - Forgetting the encoding and depending on a default that differs between environments.
- Assuming the function inspects the whole string. It only decodes the first character; to process every character, split the string first, for example with
mb_str_split(). - Writing
if (!mb_ord($s))instead of=== false. - Passing a user-supplied encoding name without validating it, which can trigger a
ValueError.
Related functions
mb_chr()converts a code point back to a character.mb_internal_encoding()gets or sets the default encoding used when$encodingisnull.IntlChar::ord()returns a code point when the intl extension is available.ord()returns the first byte of a string.
Recap
mb_ord() decodes the first character of a string in the given encoding and returns its Unicode code point as an int, or false on failure. Name the encoding explicitly, remember that only the first character is read, and use ord() only when you really want a byte.
Tested examples
$values = [
mb_ord("A", "UTF-8"),
mb_ord("\u{E9}", "UTF-8"),
mb_ord("\u{20AC}", "UTF-8"),
mb_ord("\u{1F418}", "UTF-8"),
];
echo json_encode($values), "\n";[65,233,8364,128024]
$text = "\u{20AC}uro";
echo json_encode([
'mb_ord' => mb_ord($text, 'UTF-8'),
'ord' => ord($text[0]),
'bytes' => strlen("\u{20AC}"),
]), "\n";{"mb_ord":8364,"ord":226,"bytes":3}
echo json_encode([
mb_ord("\x80", "ISO-8859-1"),
mb_ord("\x80", "Windows-1252"),
]), "\n";
try {
mb_ord("A", "NOPE");
} catch (ValueError $e) {
echo get_class($e), "\n";
}[128,8364] ValueError