Character checks7 min readExamples run on PHP 8.5.10

ctype_graph()

Learn how ctype_graph() tests whether every character in a string is printable and visible, with examples, edge cases and common mistakes.

Signature

ctype_graph(mixed $text): bool
Available since PHP 4.0.47.48.08.18.28.38.48.5All versions →

Purpose

ctype_graph() answers a narrow question: does every character in a string produce visible output? Letters, digits and punctuation qualify. Spaces, tabs, newlines and other control characters do not. It is useful for validating identifiers, tokens and codes where whitespace must never appear.

The function is part of the ctype family. These functions are fast, simple character-class checks that return a boolean and do not use regular expressions.

Signature

Parameters and defaults

$text is the only parameter, and it has no default. It is the string to test. The function returns true only when every character in the string is printable and visible.

The parameter is typed mixed for historical reasons. Older code could pass an integer, which was treated as an ASCII code if it fell between -128 and 255, and as a string of decimal digits otherwise. Since PHP 8.1 passing a non-string argument is deprecated, and the manual says a future version will treat it as a string. Pass strings only. If you start from another type, cast it with (string) or use chr() when you mean a character code.

Return value and failure cases

The function returns a bool:

  • true when the string is non-empty and every character is printable and not whitespace.
  • false when any character is a space, tab, newline, carriage return or other non-visible character.
  • false for an empty string. This is easy to overlook, because many "all characters match" checks are true for empty input, but this one is not.

It does not throw for ordinary strings. The only failure to watch for is the deprecation notice when a non-string is passed.

Example 1: basic checks

This example tests several strings and prints the results as JSON. Note that the string containing a space fails, and so does the empty string.

Example
<?php
$values = ['abc123', 'LKA#@%.54', 'hello world', "tab\t", ''];
$results = [];
foreach ($values as $value) {
    $results[] = ctype_graph($value);
}
echo json_encode($results), "\n";
Output
[true,true,false,false,false]

Example 2: validating a token safely

Because non-string arguments are deprecated, a helper that guards the type first keeps your code forward compatible. This helper accepts only strings with no whitespace.

Example
<?php
function isSafeToken(mixed $token): bool
{
    return is_string($token) && ctype_graph($token);
}

$inputs = ['api_key-42', 'api key', "line\nbreak", 'ok!', 42];
$report = [];
foreach ($inputs as $input) {
    $report[] = isSafeToken($input) ? 'valid' : 'invalid';
}
echo json_encode($report), "\n";
Output
["valid","invalid","invalid","valid","invalid"]

The integer 42 is rejected by is_string() before ctype_graph() ever sees it, so no deprecation is triggered.

The differences between ctype_graph(), ctype_print() and ctype_alnum() are small but important. A space is printable, so ctype_print() accepts it, but it creates no visible mark, so ctype_graph() rejects it. Punctuation passes ctype_graph() but fails ctype_alnum().

Example
<?php
$samples = ['a b', 'a-b', 'ab', ' '];
$rows = [];
foreach ($samples as $s) {
    $rows[] = [
        'graph' => ctype_graph($s),
        'print' => ctype_print($s),
        'alnum' => ctype_alnum($s),
    ];
}
echo json_encode($rows), "\n";
Output
[{"graph":false,"print":true,"alnum":false},{"graph":true,"print":true,"alnum":false},{"graph":true,"print":true,"alnum":true},{"graph":false,"print":true,"alnum":false}]

Edge cases

  • Empty string: always false. If empty input should be allowed, test for it separately before calling the function.
  • Single space: false, even though ctype_print() returns true for it.
  • Trailing newline: a string such as "abc\n" fails. Input read from forms or lines of text often carries one, so trim it first if that is acceptable.
  • Integers: an int is treated as a character code or as digits depending on its range, which is confusing and now deprecated. Avoid it.
  • Non-ASCII text: the check works on individual single-byte characters. Do not rely on it to classify multibyte Unicode text. For code point level checks, the manual points to IntlChar::isgraph(), or you can use a Unicode-aware regular expression.

Common mistakes

  1. Assuming empty strings pass. They do not, so required and optional fields need separate handling.
  2. Confusing it with ctype_print(). If spaces must be rejected, use ctype_graph(). If spaces are fine, use ctype_print().
  3. Passing numbers directly. A value like 65 may be treated as the letter A rather than as the text "65". Cast with (string) when you mean text.
  4. Expecting it to verify format. It only says that characters are visible. It cannot tell you whether a string is a valid email address or a well-formed token.
  5. Forgetting leftover newlines. A single trailing line break makes the whole string invalid.
  • ctype_alnum() checks for letters and digits only.
  • ctype_print() checks for printable characters, including space.
  • ctype_punct() checks for printable characters that are neither whitespace nor alphanumeric.
  • IntlChar::isgraph() checks whether a Unicode code point is a graphic character.

Recap

ctype_graph() returns true when a non-empty string contains only visible, printable characters and no whitespace. Pass real strings, remember that empty input is false, and choose ctype_print() instead when spaces should be accepted.

Tested examples

Basic visible-character checks
<?php
$values = ['abc123', 'LKA#@%.54', 'hello world', "tab\t", ''];
$results = [];
foreach ($values as $value) {
    $results[] = ctype_graph($value);
}
echo json_encode($results), "\n";
Output
[true,true,false,false,false]
Validating a token with a type guard
<?php
function isSafeToken(mixed $token): bool
{
    return is_string($token) && ctype_graph($token);
}

$inputs = ['api_key-42', 'api key', "line\nbreak", 'ok!', 42];
$report = [];
foreach ($inputs as $input) {
    $report[] = isSafeToken($input) ? 'valid' : 'invalid';
}
echo json_encode($report), "\n";
Output
["valid","invalid","invalid","valid","invalid"]
Comparing graph, print and alnum
<?php
$samples = ['a b', 'a-b', 'ab', ' '];
$rows = [];
foreach ($samples as $s) {
    $rows[] = [
        'graph' => ctype_graph($s),
        'print' => ctype_print($s),
        'alnum' => ctype_alnum($s),
    ];
}
echo json_encode($rows), "\n";
Output
[{"graph":false,"print":true,"alnum":false},{"graph":true,"print":true,"alnum":false},{"graph":true,"print":true,"alnum":true},{"graph":false,"print":true,"alnum":false}]