现有的项目最开始购买的WSTMall,使用的是Thinkphp3.2的框架,框架比较老,LNMP之前一直使用PHP5.6的版本,打算升级到7.0,结果发现凡是使用了U方法生成的url全都出问题了,本来应该是index.php?xxx全部变成了.php?xxx
跟了一下代码,发现其它环境中的服务端变更$_SERVER['PHP_SELF']可以正常获取到值/index.php,而当前环境的值却是空。
最终发现问题是由于php.ini配置中的cgi.fix_pathinfo配置导致的,部分环境安装之后,cgi.fix_pathinfo默认为1,部分编译安装的环境出于安全方面的考虑将cgi.fix_pathinfo值置成了0,就出现了上述问题。
; cgi.fix_pathinfo provides *real* PATH_INFO/PATH_TRANSLATED support for CGI. PHP's
; previous behaviour was to set PATH_TRANSLATED to SCRIPT_FILENAME, and to not grok
; what PATH_INFO is. For more information on PATH_INFO, see the cgi specs. Setting
; this to 1 will cause PHP CGI to fix its paths to conform to the spec. A setting
; of zero causes PHP to behave as before. Default is 1. You should fix your scripts
; to use SCRIPT_FILENAME rather than PATH_TRANSLATED.
; http://php.net/cgi.fix-pathinfo
;cgi.fix_pathinfo=1
解决方案
一、直接将php.ini中cgi.fix_pathinfo的值改为1,部分资料提到,启用了该值,可能会存在安全隐患,参见《nginx+cgi解析php容易出现的漏洞》和《Nginx + PHP CGI的一个可能的安全漏洞》
二、修改Thinkphp中U方法使用的常量_PHP_FILE_赋值方案
找到ThinkPHP文件夹下的ThinkPHP.php,定位到_PHP_FILE_赋值的位置,将代码if(IS_CGI)改为if(IS_CGI && $_SERVER['PHP_SELF'])
if(!IS_CLI) {
// 当前文件名
if(!defined('_PHP_FILE_')) {
if(IS_CGI && $_SERVER['PHP_SELF']) {
//CGI/FASTCGI模式下
$_temp = explode('.php',$_SERVER['PHP_SELF']);
define('_PHP_FILE_', rtrim(str_replace($_SERVER['HTTP_HOST'],'',$_temp[0].'.php'),'/'));
}else {
define('_PHP_FILE_', rtrim($_SERVER['SCRIPT_NAME'],'/'));
}
}
if(!defined('__ROOT__')) {
$_root = rtrim(dirname(_PHP_FILE_),'/');
define('__ROOT__', (($_root=='/' || $_root=='\\')?'':$_root));
}
}