如何验证 PHP 中的多语言名称?

How to validate multilingual names in PHP?

我正在使用 PHP 构建一个全球网站,我想让用户能够用他们自己的语言输入他们的名字和姓氏,而不仅仅是英语,例如:印度人将能够输入他们的名字用印度字母输入,俄罗斯人将可以用俄语字母输入他们的名字,等等。

现在,我允许名字和姓氏仅由字母组成。所以我的问题是我应该如何验证名称?我的意思是:我应该如何检查这些名称是否仅由字母组成?如果我只有英文名字会像这样:preg_match('/[^A-Za-z]/', $fname.$lname),但现在我不仅有英文字母。

注意:我无法为每种不同的语言及其字母一次又一次地编写此验证公式。

感谢您到目前为止阅读这个问题。有什么想法吗??

如果您想使用正则表达式来验证名称,则必须使用 /u 修饰符打开 Unicode 模式。在 Unicode 模式下,PCRE 字符 classes 不仅匹配,例如ASCII 字母,但包括任何语言和文字的字母字符。假设您使用了 [:alpha:] class 或 \p{L},这是 [:alpha:] class 使用 Unicode 扩展到的内容:

$fname = 'हिन्दी';
$lname = 'Русский';

preg_match('/[^[:alpha:]]/u', $fname.$lname));

此处“Russkiy”按预期验证,但“Hindi”失败。但为什么?印地语是一个 abugida 脚本,例如元音变音符号和 inherent-vowel 静音器作为其结构的一部分。人们可能会假设上面的 "ि""्""ी" 注册为字母;但是他们没有。它们属于不同的 class、\p{M} 或与其他字符组合的字符。然后,要匹配 abugida-alphabet 种语言(例如印度文,包括缅甸文、泰文、藏文等),我们应该使用:

preg_match('/([^\p{L}\p{M}])/u', $fname.$lname));

我已初步验证此组合与以下语言中预期的 letter-and-combining-mark 个字符匹配:阿卡德语、阿拉伯语、亚美尼亚语、希腊语、古吉拉特语、希伯来语、印地语、日语、马拉雅拉姆语、普通话、俄语、僧伽罗语、苏美尔语、泰米尔语、泰语。更详尽的测试待定,可以肯定地说以上内容将涵盖您的大部分字母表。

现在,完全 unicode-unrelated 关于验证名称的问题。我注意到您不允许在名称中使用空格。害怕 “Abraham Van Helsing”“Osama bin Laden” 尝试注册的那一天。然后,你不允许经期。 “V. S. Achuthanandan” 呢,人们称他为“Vee Es”,因为“Velikkakathu Sankaran”让你的嘴巴很累。那么 “J. K. Rowling” 呢?

同样,您不允许使用破折号。 "Kareem Abdul-Jabbar""Jean-Luc Picard" 呢?没有适合你的职业篮球或曲速驱动器。同样,不允许使用撇号意味着 "Count d'Artagnan" 可能会向您发起决斗,未来现在可能属于天网,因为 "Sarah O'Connor"注册失败。她不会回来了。您的网站不是那么酷。

那么好的老 Bobby Tables 又名呢? Robert'); DROP TABLE students;--,或者埃隆·马斯克的新生儿 "X Æ A-12"。在那里,我已经告诉您如何匹配任何语言的任何字母或其片段。我还暗示,如果您允许以上所有条件,几乎是避免误报的基线,那么它可能与不检查开始没有太大区别。给 "x!1യ!! O'/nul1 W0W@本@?" his/her 自由使用奇怪的名字,如果那是他们真正想要的。

延伸阅读: