我正在为CMS开发一个插件,并且有一个意料之外的问题:因为插件是启用多个启用的,所以输入可以是任何unicode字符集。该插件以 json 格式保存数据,并包含属性为value
和lookup
的对象。对于value
,一切都很好,但PHP使用lookup
属性来检索这些实体,并在某些点通过正则表达式(内容过滤器)。
问题是:
\w
(word-char)不匹配。 有没有办法将西里尔字母识别为单词字符?还有其他隐藏的捕获物吗? \u042D\u043A\u0441\u043F\u043E\u0440\u0442
。 安全不这样做吗?(服务器限制等)我所遇到的大“设计”问题源于前两个问题:
我应该允许使用非拉丁字母语言的用户将自己的字符用于lookup
属性,还是应该强制它们使用传统的“字”字符,即a,b,c等+下划线(因此是另一种语言的字母表)?我欢迎技术建议来指导这个决定(而不是UX)。
答案 0 :(得分:1)
对于非拉丁字符(例如Экспорт),正则表达式中的
\w
(word-char)不匹配。有没有办法将西里尔字母识别为单词字符?还有其他隐藏的捕获物吗?
您只需打开u
标志:
preg_match("#^\w+$#u", $str);
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起,五个和六个八位字节UTF-8序列被视为无效(分别为PCRE 7.3 2007-08-28);以前那些被认为是有效的UTF-8。
我说它有误导性,因为从上面的ideone测试中,它不仅启用了PCRE_UTF8,还启用了PCRE_UCP( Unicode字符属性),这就是你想要的行为。
以下是PCRE文档所说的内容:
PCRE_UTF8
此选项使PCRE将模式和主题视为UTF-8字符串而不是单字节字符串。但是,只有在构建PCRE以包含UTF支持时才可用。如果没有,使用此选项会引发错误。有关此选项如何更改PCRE行为的详细信息,请参阅pcreunicode页面。
PCRE_UCP
此选项更改了PCRE处理\B
,\b
,\D
,\d
,\S
,\s
,\W
,{的方式{1}}和一些POSIX字符类。默认情况下,只识别ASCII字符,但如果设置了\w
,则使用Unicode属性来对字符进行分类。有关详细信息,请参阅pcrepattern页面中有关通用字符类型的部分。如果设置PCRE_UCP
,则匹配其影响的项目之一需要更长时间。只有在使用Unicode属性支持编译PCRE时,该选项才可用。
如果你想乍一看明显的,那么PCRE_UCP
标志就会被设置,你可以在开始的时候将它插入模式中,就像那样:
PCRE_UCP
可能出现在模式开头的另一个特殊序列是
preg_match("#(*UCP)^\w+$#u", $str);
。这与设置(*UCP)
选项具有相同的效果:它会导致PCRE_UCP
和\d
等序列使用Unicode属性来确定字符类型,而不是仅识别代码小于128的字符通过查询表。
数据格式为JSON,非拉丁字符转换为JS unicodes,例如上面的
\w
。不这样做是否安全? (服务器限制等)
只要您的\u042D\u043A\u0441\u043F\u043E\u0440\u0442
标头定义了正确的编码,就不会这样做。
所以你可能想要使用类似的东西:
Content-Type
并确保您实际以UTF8发送。
但是,在转义序列中对这些字符进行编码会使整个ASCII兼容,因此您基本上可以通过这种方式完全解决问题。
我应该允许使用非拉丁字母语言的用户将自己的字符用于
header('Content-Type: application/json; charset=utf-8');
属性,还是应该强制它们使用传统的“字”字符,即a,b,c等+下划线(因此是另一种语言的字母表)?我欢迎技术建议来指导这个决定(而不是UX)。
从技术上讲,只要您的整个堆栈支持Unicode(浏览器,PHP,数据库等),我认为这种方法没有问题。只需确保测试它并在数据库中使用启用Unicode的列类型。
要小心,PHP是一种可靠的字符串支持语言,因此您必须确保使用正确的函数(避免使用非{1}}之类的非Unicode感知函数,除非您真的需要字节数。) / p>
确保一切正常运行可能需要更多的工作,但是如果你想支持它,那就没问题了。