从Nginx切换到Apache后自定义Router.php无法正常工作如何解决
问题根因
- Nginx 配置中通过
try_files规则将所有不存在的路径请求统一转发给index.php入口,由自定义路由处理,而 Apache 默认没有配置对应的转发规则,访问/admin时会直接查找磁盘上的对应文件/目录,找不到就返回404。 - 当前Apache默认的重写规则没有排除已经转发到
index.php的请求,导致内部重定向递归超过10次触发报错。 - 你的
Router.php中switch写法存在逻辑错误:preg_match返回的是匹配成功次数(0/1),和switch传入的请求URI字符串完全不匹配,这条路由规则永远不会生效。
解决方案
第一步:添加.htaccess重写规则
你的Apache配置已经开启了AllowOverride FileInfo,无需修改全局httpd配置,直接在项目根目录(也就是/var/www/virtual/USERNAME/html目录下,若你的项目入口index.php存放在public子目录,需要把站点根目录指向public,或者把.htaccess放在public目录同时调整路径)创建.htaccess文件,写入以下内容:
RewriteEngine On # 真实存在的文件/目录不转发,避免循环 RewriteCond %{REQUEST_FILENAME} !-f RewriteCond %{REQUEST_FILENAME} !-d # 其余请求全部转发到index.php,携带路径和参数,和Nginx的try_files效果一致 RewriteRule ^(.*)$ index.php/$1 [L,QSA]
第二步:修复Router.php的逻辑错误
调整路由匹配逻辑,修改后的getPageForUrl方法参考:
public function getPageForUrl() : Page { $uri = (string)$this->variablesWrapper->getRequestUri(); // 先匹配精确路由/admin if ($uri === '/admin') { if ($this->sessionManager->isAuthenticated()){ return $this->adminContentPage; } else { return $this->adminPage; } } // 再匹配正则路由 if (preg_match('/\/([A-Za-z]\w+)\/\?article\=[0-9]{1,5}/', $uri)) { return $this->articlePage; } // 默认路由 return $this->articlePage; }
如果要保留switch写法,需要把switch的判断表达式设为true,才能匹配preg_match返回的布尔结果:
public function getPageForUrl() : Page { $uri = (string)$this->variablesWrapper->getRequestUri(); switch (true) { case $uri === '/admin': if ($this->sessionManager->isAuthenticated()){ return $this->adminContentPage; } else { return $this->adminPage; } case preg_match('/\/([A-Za-z]\w+)\/\?article\=[0-9]{1,5}/', $uri): default: return $this->articlePage; } }
完成以上两步后清理浏览器缓存,即可正常访问/admin路径,重定向循环报错也会同步消失。
内容的提问来源于stack exchange,提问作者tolik518
相关产品推荐
相关产品推荐

