PHP路由开发调用其他文件类方法报非静态调用错误如何解决
错误原因
你使用[类名字符串, 方法名]格式作为call_user_func_array的回调参数时,PHP会默认尝试静态调用该类方法,但你定义的Home::index()为普通实例方法,需要依托类实例才能调用,因此触发类型错误。同时你的代码还存在一处隐藏的路由解析逻辑问题,后面同步给出修复方案。
修复代码
1. 修改APP类的Run方法
核心调整为加载控制器后先实例化对象,再用实例发起方法调用:
public function Run() { $url = $this->SplitURL(); if(file_exists("../app/controller/".strtolower($url[0]).".php")) { $this->controller = strtolower($url[0]); unset($url[0]); } require "../app/controller/".$this->controller.".php"; // 新增实例化控制器逻辑,首字母大写匹配控制器类名 $controllerClass = ucfirst($this->controller); $controllerInstance = new $controllerClass(); if(isset($url[1])) { // 改用实例判断方法是否存在,更准确 if(method_exists($controllerInstance, $url[1])) { $this->method = $url[1]; unset($url[1]); } } $this->params = array_values($url); // 回调传入实例而非类名字符串 call_user_func_array([$controllerInstance, $this->method], $this->params); }
2. 修复SplitURL方法的隐藏问题
原方法无参数时返回["home/index"]会导致路由匹配错误,调整为返回默认控制器名即可:
private function SplitURL() { if(empty($_GET['url'])) { return ["home"]; } else { return explode("/", filter_var(trim($_GET['url'], '/')),FILTER_SANITIZE_URL); } }
其他注意事项
- 确保所有控制器类名首字母大写,和实例化时的
ucfirst处理逻辑匹配 - 可额外增加类存在判断、方法访问权限判断,提升代码健壮性
内容的提问来源于stack exchange,提问作者Alex
相关产品推荐
相关产品推荐

