最近接到反馈,说网站无法在电脑微信上打开,提示 页面错误!请稍后再试~
,开启调试模式后发现报 Undefined offset: 1 in Lang.php line 204
。
问题定位
经过排查,应该是微信浏览器近期进行了更新,给服务器传递了 Accept-Language: *
。
然后框架的多语言自动侦测逻辑不严谨,导致了此次错误。
出错文件:library/think/Lang.php
出错代码:
if (isset($_GET[self::$langDetectVar])) {
// url 中设置了语言变量
$langSet = strtolower($_GET[self::$langDetectVar]);
} elseif (isset($_COOKIE[self::$langCookieVar])) {
// Cookie 中设置了语言变量
$langSet = strtolower($_COOKIE[self::$langCookieVar]);
} elseif (isset($_SERVER['HTTP_ACCEPT_LANGUAGE'])) {
// 自动侦测浏览器语言
preg_match('/^([a-zd-] )/i', $_SERVER['HTTP_ACCEPT_LANGUAGE'], $matches);
$langSet = strtolower($matches[1]);
$acceptLangs = Config::get('header_accept_lang');
if (isset($acceptLangs[$langSet])) {
$langSet = $acceptLangs[$langSet];
} elseif (isset(self::$acceptLanguage[$langSet])) {
$langSet = self::$acceptLanguage[$langSet];
}
}
关键定位:
代码语言:javascript复制// 自动侦测浏览器语言
preg_match('/^([a-zd-] )/i', $_SERVER['HTTP_ACCEPT_LANGUAGE'], $matches);
// 这里没有判断 preg_match 是否匹配到内容,直接就使用 $matches[1] ,然后就报错了
$langSet = strtolower($matches[1]);
解决办法
解决办法很简单,先判断 preg_match
,再执行后续代码。
调整后代码:
代码语言:javascript复制 if (isset($_GET[self::$langDetectVar])) {
// url 中设置了语言变量
$langSet = strtolower($_GET[self::$langDetectVar]);
} elseif (isset($_COOKIE[self::$langCookieVar])) {
// Cookie 中设置了语言变量
$langSet = strtolower($_COOKIE[self::$langCookieVar]);
} elseif (isset($_SERVER['HTTP_ACCEPT_LANGUAGE']) && preg_match('/^([a-zd-] )/i', $_SERVER['HTTP_ACCEPT_LANGUAGE'], $matches)) {
// 自动侦测浏览器语言
$langSet = strtolower($matches[1]);
$acceptLangs = Config::get('header_accept_lang');
if (isset($acceptLangs[$langSet])) {
$langSet = $acceptLangs[$langSet];
} elseif (isset(self::$acceptLanguage[$langSet])) {
$langSet = self::$acceptLanguage[$langSet];
}
}
影响版本
目前主要发现影响 ThinkPHP 5.0 和 5.1 版本,已向官方提交修复,但这两个版本已停止更新,不确定是否会合并。
- ThinkPHP 5.1 PR
- ThinkPHP 5.0 PR