ctype_punct
Checks whether every character in a string is printable punctuation, not a letter, digit or space.
ctype_punct(mixed $text): bool- Added in PHP 4.0.4
Parameters
| Parameter | Type | Description |
|---|---|---|
$text | mixed | The string to test. Every byte must be printable punctuation for the result to be true. An int between -128 and 255 is interpreted as an ASCII codepoint, which is why non-string arguments are deprecated as of PHP 8.1. |
Return value
booltrue if every character in text is printable but neither a letter, a digit nor a blank; false otherwise. An empty string always returns false.
Errors
Never throws. A non-string argument raises an E_DEPRECATED notice as of PHP 8.1; values that are neither string nor int return false.
Changelog
- PHP 8.1Passing a non-string argument is deprecated. Ints between -128 and 255 are still read as ASCII codepoints, so cast to string or use chr() explicitly.
ctype_punct() is true when every character is visible punctuation or a symbol — printable, but not a letter, digit or space. Over ASCII that is four ranges: 33-47, 58-64, 91-96 and 123-126, which covers everything from ! and @ to _, ~ and the backtick.
When to reach for it
The most common use is per character rather than per string: walking a password to confirm it contains at least one symbol, or scanning a token to find where the punctuation sits. The whole-string form is useful for classifying a lexer token such as =>, !== or ... as an operator rather than a word.
What trips people up
Characters people do not think of as punctuation are included: underscore, backtick, dollar, at-sign, caret and tilde all pass. That matters when you build a password policy — my_password already satisfies a naive "must contain a symbol" rule.
The space is not punctuation, so ctype_punct('! ') is false, and non-ASCII typographic marks such as a curly quote fail because they are multi-byte.
Example
When to use it
- Enforcing a password policy that requires at least one symbol
- Classifying a lexer token as an operator rather than an identifier
- Stripping punctuation from text before counting words
Frequently asked questions
Is the space character punctuation in PHP?
No. ctype_punct excludes blanks, so ctype_punct(' ') and ctype_punct('! ') both return false. Use ctype_graph if you want any visible character including punctuation.
Which characters count as punctuation for ctype_punct?
All printable ASCII that is neither a letter, a digit nor a space: codes 33-47, 58-64, 91-96 and 123-126. That includes the underscore, backtick, dollar sign, at sign, caret and tilde.
How do I check whether a string contains any punctuation at all?
Loop over its characters with ctype_punct and stop at the first hit, or use preg_match('/[[:punct:]]/', $s). ctype_punct on the whole string only tells you whether every character is punctuation.
More examples
Requiring a symbol in a password
Prints true, true, false. The middle case is the surprise: the underscore satisfies the rule, so a policy built this way is weaker than it looks.
<?php
function hasSymbol(string $password): bool
{
foreach (str_split($password) as $ch) {
if (ctype_punct($ch)) {
return true;
}
}
return false;
}
var_dump(hasSymbol('Str0ng!pass'));
var_dump(hasSymbol('my_password'));
var_dump(hasSymbol('plainpass1'));Stripping punctuation before counting words
Prints a frequency array where 'hello' appears twice, because the trailing comma and exclamation mark were removed before splitting. Without the strip, 'Hello,' and 'Hello' would count as different words.
<?php
$sentence = 'Hello, world! Hello again.';
$clean = '';
foreach (str_split($sentence) as $ch) {
$clean .= ctype_punct($ch) ? '' : $ch;
}
print_r(array_count_values(explode(' ', strtolower($clean))));
Discussion