Actually you don't even need the mb_string extension:

if (strlen($string) != strlen(utf8_decode($string)))
{
    echo 'is unicode';
}

And to find the code point of a given character:

$ord = unpack('N', mb_convert_encoding($string, 'UCS-4BE', 'UTF-8'));

echo $ord[1];
Answer from Alix Axel on Stack Overflow
🌐
Quora
quora.com › How-do-I-check-if-a-string-only-contains-letters-from-different-languages-like-English-or-Cyrillic-in-PHP-using-UTF-8-encoding
How to check if a string only contains letters from different languages, like English or Cyrillic, in PHP using UTF-8 encoding - Quora
How do I check if a string only ... or Cyrillic, in PHP using UTF-8 encoding? ... So, for a given string, you want to know whether it only contains characters from the alphabet of a given language, say, English. Here's how you could do that: function unicode_str_split( $s ) { ...
🌐
PHP
php.net › manual › en › function.mb-check-encoding.php
PHP: mb_check_encoding - Manual
Human Language and Character Encoding Support · Multibyte String · Multibyte String Functions · (PHP 4 >= 4.4.3, PHP 5 >= 5.1.3, PHP 7, PHP 8) mb_check_encoding — Check if strings are valid for the specified encoding · function mb_check_encoding(array|string|null $value = null, ?string $encoding = null): bool ·
🌐
GitHub
gist.github.com › Daniel-KM › 9754f18f9632423fb1a08909e9f01c04
Check and fix Unicode issues on a web server with php · GitHub
str_replace("'", "'\\''", $string) . "'"; } $filename = "File~1 -À-é-ï-ô-ů-ȳ-Ø-ß-ñ-Ч-Ł-'.Test.png"; if (escapeshellarg($filename) != escapeshellarg_unicode($filename)) { echo sprintf('An error occurs when testing function "escapeshellarg(\'%s\')": %s', $filename, escapeshellarg_unicode($filename)); } else { echo 'Success!'; } Your server is not fully compatible with Unicode.
Top answer
1 of 1
4

It is always a subjective perspective about what is binary and what not:

  • "\x46\x61\x69\x6c" can be:
    • the text Fail as per ASCII and UTF-8
    • the text 䙡楬 as per UTF-16 BE
    • the number 1180789100 as per 32bit Integer BE
    • the timestamp 2028-10-06, 12:10:12 as per DOS datetime
    • the dimensions 24902 x 27753 for two 16bit LE integers, interpreted as width and height
  • "\xf0\x9f\x98\x83" can be:
    • the text 😃 as per UTF-8
    • the text рЯШГ as per codepage 1283/10007/x-mac-cyrillic
    • the number -8.9704769e-37 as per IEEE 754 Single 32bit LE

As you see: it can be both binary and text. What you want is down to heuristics and pattern recognition, but both cannot give you the one and only correct answer, only indications. Likewise you can throw all your bytes into a text encoding detection to then see which encodings match (just like with mb_detect_encoding() (make sure to use strict mode), but at the end of the day it's only as robust the input is - if you only have i.e. 5 bytes then they most likely match at least one text encoding, while 500 bytes may or may not violate all yet known text encodings.

Checking for "\x00" is not good either, as those will occur at least in UTF-16 and UTF-32. When doing charset detection spotting NULLs may indicate UTF-16, but can also lead to wrong results like "Bush hid the facts".

Detecting file formats in general (in contrast to detecting text alone) is bit easier when signatures are defined which help identifying a format. As for texts this can only be a byte order mark, which only few encodings know and which aren't mandatory either.

🌐
Ui
php.kambing.ui.ac.id › manual › en › function.mb-check-encoding.php
PHP: mb_check_encoding - Manual
All valid code points in Unicode are considered valid when encoded with correct number of bytes (including Astral planes, i.e. four byte squences below U+10FFFF). mb_detect_encoding() provided similar results with strict parameter enabled (except for PHP 5.3.28, in which it performed worse than mb_check_encoding()) ... Unlike other comments suggest, there's no need to serialize a string to use preg_match's "u" modifier for testing if ...
🌐
PrintMyFonts
askingbox.com › tip › php-permit-only-certain-letters-numbers-and-characters-in-a-string
PHP: Permit only certain Letters, Numbers and Characters in a String
May 7, 2024 - This \p{x} extension was added in PHP version 5.1.0, so it cannot be used with older PHP versions where you have to use the normal character classes instead presented previously. When using this extension, we should also note that such a check for Unicode properties is not particularly fast due to the large number of Unicode characters. In the first code examples of this tutorial, in addition to the letters permitted by character classes or individual definitions, we also checked for numbers in our string respectively we allowed their occurrence.
Find elsewhere
🌐
GeeksforGeeks
geeksforgeeks.org › php › how-to-check-if-a-string-contains-a-specific-character-in-php
How to check if a String contains a Specific Character in PHP ? - GeeksforGeeks
July 23, 2025 - The string contains the character 'o'. The preg_match() function is used to perform a regular expression match. It allows for more complex pattern matching, including checking for the presence of specific characters using regular expressions.
Top answer
1 of 5
11

I want to explain why your attempts with regex weren't working.

Firstly, I notice ereg in your tags for this question. Please note that PHP's ereg_ functions have been deprecated; you should only use the preg_ functions.

Now, if you want to use regex for this sort of thing, you would typically use a negated character class to define a list of characters you want to allow, and then look for anything else.

A character class is a list of characters enclosed in square brackets. You can negate a character class by adding a carat symbol to the start of it. So if you wanted a string that contained only 'A', 'B' or 'C', and you wanted to get warned about strings which contained anything else, you could use something like this:

$result = preg_match("/[^ABC]/",$mystring);

Your example is basically the same (but with more characters to test, obviously), except for two points: Firstly you have characters in your list which are reserved characters in Regex, and secondly, you are using non-Ascii characters.

The Regex reserved characters can be dealt with by escaping them with a leading back-slash. You just need to know what characters are reserved. Looking at your list, I see ?, /, . and +.

The second point explains why you couldn't get it working with ereg, because the ereg functions don't support unicode. Switch to using the preg functions instead, and you'll have more luck.

You still need to specify to the regex engine that you're looking for a unicode characters. This is done by adding the u modifier to the end of the regex string.

So a shortened version of your query might look like this:

$result = preg_match("/[^èΛ¤4DTdt]/u",$mystring);

It looks like you're including new lines in your list of characters, so you may also want to add the multi-line modifier m alongside that u.

For characters which can't be written (or indeed for any character, if it's easier), you can add escape sequences for their unicode character codes. Use \uFFFF where FFFF is the hex unicode reference for the character you want to match -- eg \u00E0 matches à.

I hope that gives you a better insight into regular expressions. I should add that I'm not saying that regex is necessarily the best solution to this question, nor necessarily the only solution. I have tried to make it perform optimally by using the negated character class (which means it'll fail as soon as it finds a non-matching character, and should prevent the kind of excessive backtracking which can cause regex expressions to be quite slow sometimes), so it should be reasonably performant, but I haven't tested it against other solutions.

2 of 5
4

As far as you're concerned for single byte charsets, you can do it with string functions:

$charset = 'abc';
$test = 'abcd';
$ofCharset = strlen($test) === strspn($test, $charset); # FALSE

Otherwise you must split your string into array entries of one char each and then compare against a character table which could be a keyed array as well containing the character of the charset as key.


Nevertheless, as it is visible from your question with closer attention, the character set you're asking about is the basic character set of GSM 03.38. It's 7bit, so you can generate the charset array quickly and implode it into a string for strspn():

// alternative form:
// $characters = implode(range("\0", "\177"));
$characters = implode('', range("\0", "\177"));
$result = strlen($string) === strspn($string, $characters);
assert(is_bool($result));

In case you've got the multibyte string extension (mb_* family of functions) available, you can check the string with even less setup:

$test = 'abcd';
$ofCharset = mb_check_encoding($test, 'ASCII') # TRUE

This works because ASCII is 7bit as well and can be used as a stand-in.

🌐
W3Docs
w3docs.com › php
Unicode character in PHP string | W3Docs
Note that the \u{...} escape sequence requires PHP 7.0 or higher. You can also use the html_entity_decode function to convert HTML entities (such as 💗) to Unicode characters in a PHP string.
🌐
GitHub
gist.github.com › cferdinandi › 6688744
Test strings for letters, numbers, and special characters. Returns true if they exist, false if they don't. Forked from http://stackoverflow.com/a/9588010/1293256 · GitHub
Test strings for letters, numbers, and special characters. Returns true if they exist, false if they don't. Forked from http://stackoverflow.com/a/9588010/1293256 - has-characters.php