第一个问题
对于非拉丁字符(例如Экспорт),正则表达式中的\w(字字符)不匹配任何内容。有没有办法将西里尔字符识别为单词字符?还有其他隐藏的陷阱吗?
您只需要打开u 标志:
preg_match("#^\w+$#u", $str);
Demo.
PHP docs 在这里具有误导性:
你 (PCRE_UTF8)
此修饰符打开与 Perl 不兼容的 PCRE 的附加功能。模式和主题字符串被视为 UTF-8。此修饰符在 Unix 上的 PHP 4.1.0 或更高版本以及 win32 上的 PHP 4.2.3 中可用。自 PHP 4.3.5 起检查模式和主题的 UTF-8 有效性。无效的主题将导致 preg_* 函数不匹配;无效的模式将触发 E_WARNING 级别的错误。自 PHP 5.3.4 (resp. PCRE 7.3 2007-08-28) 起,五个和六个八位字节的 UTF-8 序列被视为无效;以前那些被认为是有效的 UTF-8。
我说这是误导,因为从上面的 ideone 测试中,它不仅启用了 PCRE_UTF8,而且还启用了 PCRE_UCP(Unicode 字符属性),这是您想要的行为。
以下是 PCRE 文档的说法:
PCRE_UTF8
此选项使 PCRE 将模式和主题都视为 UTF-8 字符串而不是单字节字符串。但是,仅当 PCRE 构建为包含 UTF 支持时才可用。如果不是,则使用此选项会引发错误。 pcreunicode 页面中提供了此选项如何更改 PCRE 行为的详细信息。
PCRE_UCP
此选项更改 PCRE 处理 \B、\b、\D、\d、\S、\s、\W、\w 和一些 POSIX 字符类的方式。默认情况下,仅识别 ASCII 字符,但如果设置了PCRE_UCP,则使用 Unicode 属性代替对字符进行分类。更多详细信息在 pcrepattern 页面中有关通用字符类型的部分中给出。如果您设置PCRE_UCP,匹配它影响的项目之一需要更长的时间。仅当 PCRE 已使用 Unicode 属性支持编译时,该选项才可用。
如果你想让它一目了然,PCRE_UCP 标志将被设置,你可以在开始时将它插入到模式本身中,就像这样:
preg_match("#(*UCP)^\w+$#u", $str);
另一个可能出现在模式开头的特殊序列是(*UCP)。这与设置PCRE_UCP 选项的效果相同:它使\d 和\w 等序列使用Unicode 属性来确定字符类型,而不是通过查找表仅识别代码小于128 的字符。
第二个问题
数据格式为 JSON,非拉丁字符转换为 JS unicode,例如:\u042D\u043A\u0441\u043F\u043E\u0440\u0442。不这样做安全吗? (服务器限制等)
只要您的 Content-Type 标头定义了正确的编码,就不要这样做是安全的。
所以你可能想使用类似的东西:
header('Content-Type: application/json; charset=utf-8');
并确保您确实以 UTF8 发送它。
但是,将这些字符编码为转义序列可以使整个 ASCII 兼容,因此您基本上可以通过这种方式完全消除问题。
设计题
我是否应该允许使用非拉丁字母语言的用户将自己的字符用于 lookup 属性,或者我应该强制他们使用传统的“单词”字符,即 a、b、c 等 + 下划线(因此另一种语言的字母表)?我欢迎技术 建议来指导这个决定(不是 UX 建议)。
从技术上讲,只要您的整个堆栈都支持 Unicode(浏览器、PHP、数据库等),我认为这种方法没有问题。只需确保对其进行良好测试并在您的数据库中使用支持 Unicode 的列类型即可。
请注意,PHP 是一种糟糕的字符串支持语言,因此您必须确保使用正确的函数(避免使用不支持 Unicode 的函数,如 strlen 等,除非您真的想要字节数)。
确保一切都按预期运行可能需要做更多的工作,但如果这是您想要支持的东西,那没有问题。