我们使用ZendFramework2框架的时候,经常会在控制器里面进行重定向操作,例如:在UserController.php中,用户请求/user/index,如果这时用户没有登录,就要使用“$this->redirect()->toRoute();”自动重定向到/user/login,如下
public function indexAction()
{
$logginedName = $this->IsLoggined();
if (!$logginedName){
return $this->redirect()->toRoute('user', array(
'action' => 'login'
));
}
return new ViewModel(array(
'users' => $this->getUserTable()->fetchAll(),
));
}
对于控制器中的重定向操作,如果php.ini配置的output_buffering设置的是off,则有时候可能会出现“$this->redirect()->toRoute();”失效的情况,具体表现就是php执行到“$this->redirect()->toRoute();”就终止输出了。
造成这种问题的原因可能有三种:
1)“$this->redirect()->toRoute();”这句之前有echo输出;
2)“$this->redirect()->toRoute();”这句之前的php代码块结束符“?>”之后有字符串输出(包括空格);
3)src/User/Controller、src/User/From或者src/User/Model目录下的*.php文件含有bom头。
bom头是windows自带的一些记事本等软件在保存一个以utf-8编码的文件的时候,在文件的开始位置插入的三个不可见的字符(0xEF、0xBB和0xBF)。php不会识别这三个字符,而直接将这三个字符输出到http的content。这样的话,如果php.ini配置的output_buffering设置的是off,php就无法再执行header函数来修改http头,而“$this->redirect()->toRoute();”就是通过修改http头来实现重定向的,因此就出现错误,ZendFramework2碰到这个错误就自动终止输出了。
对于第一种和第二种情况,只需要检查代码就可以避免,对于第三种情况,可以使用下面的方法。
将以下的代码拷贝保存为clearBom.php文件,将clearBom.php文件拷贝到ZendFramework2项目的module/目录下,然后在浏览器直接访问http://....../module/clearBom.php(具体URL根据项目调整)就可以将module/目录及其子目录下的所有*.php文件的bom头去除了:
function clearBom($dirname){
$fileList = scandir($dirname);
foreach ($fileList as $file){
$pathfile = $dirname."/".$file;
if (is_dir($pathfile)){
if ($file != "." && $file != "..")
clearBom($pathfile);
}else{
if (strlen($file) > 4 && strtolower(substr($file, -4) == ".php")) {//只处理*.php文件
$content = file_get_contents($pathfile);
if (strlen($content) > 3){
$char[1] = substr($content, 0, 1);
$char[2] = substr($content, 1, 1);
$char[3] = substr($content, 2, 1);
if (ord($char[1]) == 239 &&
ord($char[2]) == 187 &&
ord($char[3]) == 191){
$restcontent = substr($content, 3);
$f = fopen($pathfile, "w");
fwrite($f, $restcontent);
fclose($f);
}
}
}
}
}
}
clearBom(__DIR__);