如何验证用户提供的mb_*()函数的字符集字符串


How to validate a user-supplied charset string for mb_*() functions?

变量($my_charset)保存用户提供的字符集/编码字符串,如UTF-8, ISO-8859-1Windows-1251。我如何通过编程来验证它?我也有用户提供的文本(下面的$my_text)可供使用,应该是在这种编码中。

我的解决方案:

$is_valid = @mb_check_encoding($my_text, $my_charset);

我不喜欢它,因为:

  • 它使用错误控制操作符@来抑制错误(如Warning: mb_check_encoding(): Invalid encoding" some-invalid-encoding"),这是糟糕的编程实践。
  • false返回值不能帮助我区分错误的字符集字符串与有效的字符集字符串和错误编码的文本。

PHP提供了mb_list_encodings()mb_encoding_aliases()函数,我可以使用它们来构建所有支持的编码列表,并以不区分大小写的方式检查用户提供的编码是否包含在该列表中。我也不喜欢这个方案,太过分了。对于mb_list_encodings()返回的每个项目(超过50),需要调用mb_encoding_aliases()

你有更好的解决办法吗?

您可以自己验证所提供的字符集:

$is_valid = @mb_check_encoding('', $my_charset);

错误控制操作符可能很讨厌,但在这里使用它并没有错。它存在的原因超越了邪恶。而且您也不必担心将不支持的编码与错误编码的文本混淆。


如果你仍然想避免这种情况,使用mb_list_encodingsmb_encoding_aliases并不是多余的- ~50个编码,每个有~4个别名是不是很多。但是,如果你不想在每个请求上运行这些,你可以使用它们来生成一个静态数组并加载它。

例子:

$encodings = mb_list_encodings();
foreach ($encodings as $enc) {
    $encodings = array_merge($encodings, mb_encoding_aliases($enc));
}
$encodings = array_change_key_case(array_fill_keys($encodings, true));
var_export($encodings);

这将转储有效的PHP,您可以直接粘贴到PHP文件中。你可以用serializejson_encode来序列化它,然后再反序列化,不管你喜欢什么。

它使用编码作为键而不是值,因此查找将在O(1)时间内完成,而不是O(n)时间。array_change_key_case是用来小写它们的,方便查找:

$is_valid = isset($encodings[strtolower($my_charset)]);