设计决策:将JSON中的西里尔字符与PHP匹配
我正在为CMS开发一个插件,但有一个意想不到的问题:因为插件支持多语言,所以输入可以是任何unicode字符集。该插件以json格式保存数据,并包含具有属性设计决策:将JSON中的西里尔字符与PHP匹配,php,regex,json,character-encoding,http-headers,Php,Regex,Json,Character Encoding,Http Headers,我正在为CMS开发一个插件,但有一个意想不到的问题:因为插件支持多语言,所以输入可以是任何unicode字符集。该插件以json格式保存数据,并包含具有属性value和lookup的对象。对于value一切正常,但是PHP使用lookup属性来检索这些实体,并在某些时候通过regex(内容过滤器)进行检索。 问题是: 对于非拉丁字符(例如,Бimk_ССПСМ),正则表达式中的\w(单词char)不匹配任何内容有没有办法将西里尔字母字符识别为单词字符?还有其他隐藏的捕获物吗? 数据格式为JSON
value
和lookup
的对象。对于value
一切正常,但是PHP使用lookup
属性来检索这些实体,并在某些时候通过regex(内容过滤器)进行检索。
问题是:
\w
(单词char)不匹配任何内容有没有办法将西里尔字母字符识别为单词字符?还有其他隐藏的捕获物吗?\u042D\u043A\u0441\u043F\u043E\u0440\u0442
不这样做安全吗?(服务器限制等)查找
属性,还是应该强制他们使用传统的“word”字符,即a、b、c等+下划线(因此是另一种语言的字母表)?我希望能有一个技术建议来指导这个决定(而不是用户体验)。第一个问题
对于非拉丁字符(例如,Бimk_ССПСМ),正则表达式中的\w
(单词char)不匹配任何内容。有没有办法把西里尔文字字符识别为单词字符?还有其他隐藏的陷阱吗
您只需打开u
标志:
preg_match("#^\w+$#u", $str);
这些数据在这里具有误导性:
u(PCRE\u UTF8
)此修饰符打开与Perl不兼容的PCRE的附加功能。模式和主题字符串被视为UTF-8。此修饰符可从Unix上的PHP4.1.0或更高版本以及win32上的PHP4.2.3获得。从PHP4.3.5开始检查模式和主题的UTF-8有效性。无效的主题将导致preg_*函数不匹配;无效模式将触发级别E_警告错误。自PHP 5.3.4(分别为PCRE 7.3 2007-08-28)以来,五个和六个八位组UTF-8序列被视为无效;以前,这些被认为是有效的UTF-8 我说这是误导性的,因为从上面的ideone测试来看,它不仅启用了PCRE_UTF8,而且还启用了PCRE_UCP(Unicode字符属性),这是您在这里想要的行为 以下是PCRE文档对此的描述:
PCRE\u UTF8
此选项使PCRE将模式和主题视为UTF-8字符的字符串,而不是单字节字符串。但是,只有当PCRE构建为包含UTF支持时,它才可用。否则,使用此选项会引发错误。有关此选项如何更改PCRE行为的详细信息,请参见pcreunicode页面
PCRE\U UCP
此选项更改PCRE处理
\B
,\B
,\D
,\D
,\S
,\S
,\W
,\W
,以及某些POSIX字符类的方式。默认情况下,仅识别ASCII字符,但如果设置了PCRE\u UCP
,则使用Unicode属性对字符进行分类。pcrepattern页面中有关泛型字符类型的部分提供了更多详细信息。如果设置了PCRE\u UCP
,则匹配其中一个受影响的项目需要更长的时间。只有使用Unicode属性支持编译PCRE时,此选项才可用
如果您想让它一目了然,将设置PCRE\u UCP
标志,您可以在开始时将其插入图案本身,如下所示:
preg_match("#(*UCP)^\w+$#u", $str);
另一个可能出现在模式开头的特殊序列是(*UCP)
。这与设置PCRE\u UCP
选项的效果相同:它使序列(如\d
和\w
)使用Unicode属性确定字符类型,而不是通过查找表仅识别代码小于128的字符
第二个问题
数据格式为JSON,非拉丁字符转换为JS unicodes,例如:\u042D\u043A\u0441\u043F\u043E\u0440\u0442
。不这样做安全吗?(服务器限制等)
只要内容类型
标题定义了正确的编码,就可以安全地不这样做
因此,您可能需要使用以下内容:
header('Content-Type: application/json; charset=utf-8');
确保你真的用UTF8发送
然而,在转义序列中编码这些字符会使整个ASCII兼容,因此基本上可以通过这种方式完全消除问题
设计问题
我应该允许使用非拉丁字母表语言的用户使用自己的字符进行查找
属性,还是应该强制他们使用传统的“word”字符,即a、b、c等+下划线(因此是另一种语言的字母表)?我希望能有一个技术建议来指导这个决定(而不是UX)
从技术上讲,只要整个堆栈支持Unicode(浏览器、PHP、数据库等),我认为这种方法没有问题。只需确保测试良好,并在数据库中使用支持Unicode的列类型即可
小心,PHP是一种糟糕的字符串支持语言,因此您必须确保使用正确的函数(除非您确实需要字节计数,否则请避免使用非Unicode的函数,如strlen
等)
要确保一切正常运行,可能需要做更多的工作,但如果你想支持这一点,那就没有问题。这不是一个问题。我能回答第一部分,但不能回答第二部分。你会接受谁的答案?@Stribizev发现谜题的任何部分都会得到奖励。你建议我将这个问题重新措辞并分成2/3个问题吗?谢谢你的严格回答!A.