Signature
ctype_alpha(mixed $text): boolPurpose
ctype_alpha() answers one narrow question: is every character in a string a letter? It returns a plain boolean, so it works well as a quick guard for short tokens such as initials, country-style codes or simple identifiers. In the default C locale, which PHP uses unless you change it, the letters are just A-Z and a-z.
Signature
Parameters and defaults
$text is the value to test. It has no default and is required. Pass a string. The function examines the string byte by byte and requires each byte to be a letter in the current locale.
The manual also describes a legacy behavior for integers. An integer from -128 to 255 is treated as the ASCII code of one character, and any other integer is treated as its decimal digits. Passing a non-string argument has been deprecated since PHP 8.1. If you start from a number, convert it deliberately with a string cast, or use chr() if you really mean a character code.
Return value and failure cases
The function returns true only if every character is a letter. It returns false if any character is a digit, space, punctuation mark, newline or other non-letter. An empty string always gives false, which is different from what many people expect from an "all characters match" test. The function does not throw for ordinary string input; the result tells you whether the check passed.
Example 1: basic checks
The first example runs several strings through the function and prints the results as JSON. Note the empty string at the end.
$inputs = ['KjgWZC', 'arf12', 'hello world', ''];
$results = [];
foreach ($inputs as $input) {
$results[$input] = ctype_alpha($input);
}
echo json_encode($results, JSON_UNESCAPED_UNICODE | JSON_UNESCAPED_SLASHES), "\n";{"KjgWZC":true,"arf12":false,"hello world":false,"":false}
The digits in arf12 and the space in hello world make those tests fail, and the empty string fails by definition.
Example 2: a small description helper
Wrapping the check in a function keeps calling code readable. This example also shows that an accented letter written in UTF-8 does not count in the default C locale, because it is stored as bytes above the ASCII range.
function describe(string $value): string
{
return ctype_alpha($value) ? 'letters only' : 'not letters only';
}
foreach (['Alpha', 'Beta2', 'snake_case', 'café'] as $value) {
echo json_encode($value, JSON_UNESCAPED_UNICODE), ': ', describe($value), "\n";
}"Alpha": letters only "Beta2": not letters only "snake_case": not letters only "café": not letters only
Underscores are not letters, so snake_case is rejected as well.
Example 3: comparing with case checks
The manual notes that, for a single character in the standard C locale, ctype_alpha() is equivalent to ctype_upper() || ctype_lower(). For longer strings the functions differ: mixed case is still alphabetic, but it is neither entirely upper nor entirely lower case.
foreach (['PHP', 'php', 'Php'] as $word) {
echo $word, ' ', json_encode([ctype_alpha($word), ctype_upper($word), ctype_lower($word)]), "\n";
}PHP [true,true,false] php [true,false,true] Php [true,false,false]
The three booleans are alpha, upper and lower, in that order. Php passes the alphabetic test but fails both case tests.
Edge cases
- Empty string: always
false. If an empty value should be allowed, test for it separately before calling the function. - Whitespace and line endings: a trailing newline or space makes the whole check fail. Trim user input first if surrounding whitespace should be ignored.
- Non-ASCII text: a UTF-8 letter such as
éis made of multiple bytes and is not a letter in the C locale. This function is not a Unicode-aware test. For Unicode letters, use a different tool, such as a PCRE pattern with theumodifier and\p{L}, or the Intl extension if it is available. - Locale: the manual says letters come from the current locale. Changing the locale with
setlocale()can change the result for bytes outside ASCII, so avoid relying on it in portable code. - Non-string values: integers are interpreted in the legacy way described above and are deprecated as arguments. Do not depend on that behavior.
Common mistakes
- Expecting true for an empty string. Required form fields and optional fields need different handling.
- Validating human names with it. Names can contain spaces, hyphens, apostrophes and non-ASCII letters, so a strict ASCII-letter check will reject valid input.
- Passing numbers.
ctype_alpha(65)relies on the deprecated ASCII-code interpretation. Cast to a string or callchr(65)to state your intention. - Assuming it checks Unicode. It works with bytes and the current locale, not with Unicode code points.
- Forgetting that digits fail. Identifiers such as
abc1are not alphabetic; usectype_alnum()when digits are acceptable.
Related functions
ctype_upper()checks for uppercase letters.ctype_lower()checks for lowercase letters.ctype_alnum()allows letters and digits.setlocale()sets locale information that can affect ctype functions.IntlChar::isalpha()checks whether a code point is a letter, when the Intl extension is available.
Recap
Use ctype_alpha() for a fast ASCII-oriented test that a non-empty string contains only letters. Remember that an empty string returns false, whitespace and punctuation fail, non-ASCII UTF-8 text does not pass in the default C locale, and non-string arguments are deprecated.
Tested examples
$inputs = ['KjgWZC', 'arf12', 'hello world', ''];
$results = [];
foreach ($inputs as $input) {
$results[$input] = ctype_alpha($input);
}
echo json_encode($results, JSON_UNESCAPED_UNICODE | JSON_UNESCAPED_SLASHES), "\n";{"KjgWZC":true,"arf12":false,"hello world":false,"":false}
function describe(string $value): string
{
return ctype_alpha($value) ? 'letters only' : 'not letters only';
}
foreach (['Alpha', 'Beta2', 'snake_case', 'café'] as $value) {
echo json_encode($value, JSON_UNESCAPED_UNICODE), ': ', describe($value), "\n";
}"Alpha": letters only "Beta2": not letters only "snake_case": not letters only "café": not letters only
foreach (['PHP', 'php', 'Php'] as $word) {
echo $word, ' ', json_encode([ctype_alpha($word), ctype_upper($word), ctype_lower($word)]), "\n";
}PHP [true,true,false] php [true,false,true] Php [true,false,false]