Strings7 min readExamples run on PHP 8.5.10

ord()

Learn how ord() converts the first byte of a string to an integer from 0 to 255, why it is not Unicode-aware, and how to avoid common mistakes.

Signature

ord(string $character): int

Purpose

ord() reads the first byte of a string and returns it as an unsigned integer between 0 and 255. It is the counterpart of chr(), which turns a number in that range back into a one-byte string. Typical uses are classifying ASCII characters, building simple checksums, and inspecting the raw bytes of binary data.

The important word is byte. PHP strings are sequences of bytes, and ord() has no knowledge of text encodings. With a single-byte encoding such as ASCII, the byte value matches the character's position in the character table. With UTF-8 or UTF-16 it will never give you a Unicode code point, only the value of the first byte of that character's encoding.

Signature

Parameters and defaults

Parameter Meaning Default
$character The string whose first byte is examined. It is meant to be a single character (one byte). none, required

There are no optional parameters. If you pass a longer string, only the first byte is used and the rest is ignored. That is deprecated as of PHP 8.5, so pass $s[0] explicitly.

Return value and failure cases

ord() always returns an int from 0 to 255. It does not return false and does not signal failure through a return value. Some details worth knowing:

  • An empty string gives 0, the same result as for a string starting with a NUL byte, and is deprecated as of PHP 8.5.
  • A non-string argument is subject to the usual type juggling rules for the calling file. Under declare(strict_types=1), passing an integer raises a TypeError.
  • As of PHP 8.5.0, passing a string that is not exactly one byte long, including an empty string, is deprecated. Pass exactly one byte so that your code stays free of deprecation notices.

Example 1: basic values and the first-byte rule

The first example shows ASCII letters, a newline and the first byte of a longer string.

Example
<?php
echo json_encode([ord('A'), ord('a'), ord("\n"), ord('Hello'[0])]), PHP_EOL;
Output
[65,97,10,72]

Uppercase A is 65, lowercase a is 97, and a line feed is 10. 'Hello'[0] is H, so it yields 72. Passing 'Hello' itself would also give 72, but strings that are not exactly one byte, including the empty string, are deprecated as of PHP 8.5.

Example 2: looking at the bytes of a UTF-8 character

A single visible character in UTF-8 can occupy several bytes. To see them all, loop over the string by byte offset and call ord() on each one-byte slice.

Example
<?php
$elephant = "\u{1F418}";
$bytes = [];
for ($i = 0; $i < strlen($elephant); $i++) {
    $bytes[] = ord($elephant[$i]);
}
echo json_encode($bytes), PHP_EOL;
Output
[240,159,144,152]

The elephant emoji is encoded in UTF-8 as four bytes, so the loop collects four values. Calling ord($elephant) directly would return only the first of them, 240 (with a deprecation notice in PHP 8.5), which is not the code point of the emoji. For code points, use a multibyte-aware function such as mb_ord() (from the mbstring extension) or IntlChar::ord().

Example 3: a small ASCII classifier

Because ASCII letters occupy contiguous ranges, comparing byte values is a compact way to classify them.

Example
<?php
function isAsciiUpper(string $char): bool
{
    $value = ord($char);
    return $value >= 65 && $value <= 90;
}

echo json_encode([isAsciiUpper('Q'), isAsciiUpper('q'), isAsciiUpper('[')]), PHP_EOL;
Output
[true,false,false]

Uppercase A to Z are 65 to 90. The lowercase q is 113, and [ is 91, so both are rejected. This only works for ASCII. Accented or non-Latin capitals are multi-byte in UTF-8 and need different tools.

Edge cases

  • Multi-byte characters. ord() returns the lead byte only. For UTF-8 text this is a value of 128 or higher for any non-ASCII character.
  • Values above 127. The result is always unsigned. You will not see negative numbers, unlike in some other languages where bytes are signed.
  • Empty input. The result 0 is ambiguous with a real NUL byte and PHP 8.5 deprecates it, so check $s === '' first if the difference matters.
  • Round trips. chr(ord($c)) returns the first byte of $c as a one-byte string. It equals $c only when $c is exactly one byte long.

Common mistakes

  1. Expecting a Unicode code point. Developers often call ord('é') and are surprised by 195 rather than 233. The function is byte-based by design.
  2. Passing a whole word. ord($word) inspects only the first byte and is deprecated as of PHP 8.5. Iterate over bytes explicitly when you need all of them.
  3. Iterating a UTF-8 string and treating each byte as a character. Looping with strlen() and $s[$i] visits bytes, not characters.
  4. Ignoring empty strings. An empty value returns 0 (with a deprecation notice in PHP 8.5), which can look like valid data in a checksum or classifier.
  5. Comparing against the wrong case range. Uppercase and lowercase ASCII letters differ by 32, so range checks must use the correct bounds.
  • chr() creates a one-byte string from a number and is the inverse of ord().
  • mb_ord() returns the Unicode code point of a character in a given encoding.
  • IntlChar::ord() returns a code point when the intl extension is available.
  • strlen() counts bytes, which is the right bound for byte loops.

Recap

ord() takes the first byte of a string and returns it as an integer from 0 to 255. It is encoding-unaware, and as of PHP 8.5 longer and empty strings are deprecated, so pass exactly one byte. Use it for ASCII and raw-byte work, and reach for multibyte-aware functions when you need Unicode code points.

Tested examples

Basic values and the first-byte rule
<?php
echo json_encode([ord('A'), ord('a'), ord("\n"), ord('Hello'[0])]), PHP_EOL;
Output
[65,97,10,72]
Collecting the bytes of a UTF-8 character
<?php
$elephant = "\u{1F418}";
$bytes = [];
for ($i = 0; $i < strlen($elephant); $i++) {
    $bytes[] = ord($elephant[$i]);
}
echo json_encode($bytes), PHP_EOL;
Output
[240,159,144,152]
A small ASCII uppercase classifier
<?php
function isAsciiUpper(string $char): bool
{
    $value = ord($char);
    return $value >= 65 && $value <= 90;
}

echo json_encode([isAsciiUpper('Q'), isAsciiUpper('q'), isAsciiUpper('[')]), PHP_EOL;
Output
[true,false,false]