正在做一个基于ZendFramework的项目,要从wamp平台移植到LNMP
平台。于是我在VMware上安装了一个CentOS6,并且编译安装了Nginx + php-fpm + MySQL
环境。
出现问题
在看到phpinfo()界面以后,赶紧配置Nginx的虚拟主机,把ZendFramework项目上传到CentOS里。正常打开项目,但登录后就出现在项目主页与登录界面两个页面之间无限死循环跳转,跳转间隔大约一到两秒,整个页面都是空白,没有任何字符与报错提示。
没有开启URL重写规则
因为我在项目下发现有点.htaccess
文件,所以就直接认定可能是因为.htaccess文件里可能写了什么东西,没有被Nginx解析到,所以出现无限死循环跳转情况。.htaccess文件时Apache动态加载配置文件,只要放在站点根目录下,就会自动被解析,并且不需要重新启动Apache服务。
于是开始搜索Nginx+ZendFramework重写规则,然后贴进nginx.conf的server块,重启Nginx,刷新浏览器测试。
但最后还是没有解决问题,被迫放弃。
想到是pathinfo的问题
调到晚上十点半,还是没有找到问题,只好关电脑回家休息。走到路上我突然想会不会是因为没有开启pathinfo模式?
于是第二天开始配置pathinfo模式,开始搜索Nginx+pathinfo模式,然后修改nginx.conf,重启Nginx,浏览器测试。
最后,同样还是没有解决登录后无限死循环跳转的问题。
此时开始感到这个问题有点让我感到后怕了,网上所有找到的方法都尝试了一遍都不奏效。
配置ThinkPHP做DEMO
一度怀疑是pathinfo没有配置好的缘由,我只好配置一个ThinkPHP来验证是否开启了pathinfo,因为ThinkPHP默认的URL就是a.com/xx/xx格式。
ThinkPHP不大,一会就下完了。因为已经有一段时间没有碰ThinkPHP了,只好读读文档,一步步搭建环境。当配置好浏览器能访问后,我加了一个user控制器并在控制器下写了一个add的方法做测试。
于是使用a.com/user/add
这样的URL刷新浏览器,修改nginx.conf,重启Nginx。
一开始从网上搜索Nginx+ThinkPHP的相关信息进行配置,不太顺利,都报错。下班后立即冲回家里用再继续,结果终于找到解决方法了,请参考我前两天写的文章《配置nginx支持pathinfo模式》。一阵狂喜!
看看时间,已深夜两点,倒头睡!
再测试还是有问题
以为在ThinkPHP下测试通过了,把设置pathinfo的那段nginx.conf代码粘贴到ZendFramework项目的server中,保存重启Nginx,测试!
还是无限跳转的原因,有点崩溃了。
配置ZendFramework的DEMO
不愿放弃,感觉可能能解决的,因为wamp组建都能跑的站点,Linux下没有理由跑不了。为了更确定问题的原因我只好下载了一个ZendFramework开始学着搭建一个简单环境,为的就是测试Nginx+ZendFramework的pathinfo模式是否开启,是否支持a.com/xx/xx这样的URL。
如法炮制,我把在ThinkPHP下测试通过的那一段开启pathinfo模式的代码拷贝过来,保存nginx.conf重启测试。发现在自己搭建的ZendFramework环境下可以解析pathinfo路由模式。
看来就不是pathinfo的问题导致项目无限跳转死循环的原因了。
重新确定问题
到这里已经没有解决方案,于是只好认认真真的去看下跳转的变化,经过仔细观察发现
每次打开浏览器登录后会跳回原页面,而原页面又跳回登录页面,循环跳转。
我开始想,当第一次启动浏览器打开项目就跳到另外一个域下的登录界面,而登录失败会正常提示,登录成功则跳回项目主页,项目主页又跳回登录界面,间隔都很短只有一两秒钟,页面都没有任何内容。
我假定
首次打开项目 > 判断没有登录 > 跳到登录界面 > 登陆后 > 跳回原项目首页 > 原项目首页却判断没有登录 >
又跳回登录界面 > 然而登录页面的域下已经记录登录的Cookie或者Seesion了 > 又跳回项目首页....
不断死循环。
初步判断是因为登录后没有写上cookie或者session导致。但为何项目在wamp下却能写cookie或者session,而linux环境下却出错了呢?于是测试了以下PHP下session的存取,发现都正常。
注意.htaccess的内容
为了判断是是.htaccess里的内容我在Linux下没有配置好而导致登录后无限死循跳转,我把wamp环境下把项目的.htaccess文件给删除了,打开浏览器,输入项目网址,登录。果然出现了跟Linux下登录后无限死跳转循环的症状。这一下,我更确定是.htaccess里可能又某项设置没有被写到nginx.conf中。于是只好认认真真读了以下.htaccess文件
.htaccess
php_value session.auto_start 1
RewriteEngine On
RewriteCond %{REQUEST_FILENAME} -s [OR]
RewriteCond %{REQUEST_FILENAME} -l [OR]
RewriteCond %{REQUEST_FILENAME} -d
RewriteRule ^.*$ - [NC,L]
RewriteRule ^.*$ index.php [NC,L]
我注意到第一行代码
php_value session.auto_start 1
这句代码是开启session的意思,联想到我之前的推断可能登录后没有写cookie或者session导致无限死循环在两个页面之间跳转。
于是我赶紧在php.ini
里加了一句
...
session.auto_start=1
...
保存php.ini,重启php-fpm,测试成功!登录后不在死循环跳转。心中不免感叹一番,折腾了将近一周,原来就是这个小小的问题导致的。
想说的话
经过这次调错,有几点想对于正在学习程序的童鞋说说几点
- 遇到问题的时候,要确定问题方向。我在这次的调错中,就确定方向错了,以为是pathinfo配置的问题。结果最后原来是session没有开启导致。
- 遇到问题,要尽量利用已有的条件去确定问题的原因。比如日志,比如页面报错的信息等等,比如配置环境。然后想想怎么解决,网上搜索的资料应该要加以判断,切忌遇到问题就立马到网上搜索不管三七二一。
- 其实以上我解决session的问题是把
session.auto_start=1
写到php.ini里,这样就会所有PHP的页面都会默认开启session。而原项目下是写到.htaccess文件里,只对特定的区域开启。所以在nginx中如何解决这个问题?比如也可以写一个.htaccess文件,在nginx.conf中包含进来,或者在项目的全局配置里直接session_start()
开启session。