当uri未在路由器类中注册时,引发404错误


Throw 404 error when uri is not registered in the router class

我从昨天开始尝试,但找不到任何资源来帮助我。为了学习,我正在构建自己的自定义MVC。当一个uri没有在router类中注册时,它会抛出一条404错误消息。我尝试了很多技巧,但都没用。

router.php

$router->get('', 'homeController@index', 'home');
$router->get('contact', 'contactController@index', 'contact');
$router->get('contact/locations', 'contactController@locations', 'contact');

controller.class.php

class Controller{
    public function controller($ContollerMethod = null){
        $contoller = explode('@', $ContollerMethod);
        if( !empty($contoller[0]) ){
            return $contoller[0];
        }
    }
    public function method($ContollerMethod = null){
        $method = explode('@', $ContollerMethod);
        if( !empty($method[1]) ){
            return $method[1];
        }
    }
    public function view($view = null){
        if( empty($view) ){
            $view = 'page';
        }
        $file = site_path() . '/app/views/' . $view . '.php';
        require_once($file);
    }
    public function render($ContollerMethod = null, $view = null, $data = array() ){
        $controller = $this->controller($ContollerMethod);
        $method = $this->method($ContollerMethod);
        if( file_exists(site_path() . '/app/controllers/' . $controller . '.php') ){
            require_once(site_path() . '/app/controllers/' . $controller . '.php');
            if( !method_exists($controller, $method) ){
                die('No method ''<em>' . $method . '</em>'' exists on Controller ''<em>' . $controller . '</em>''');
            }
            $params = array();
            call_user_func_array( [$controller, $method], $params );
            $master = site_path() . '/app/views/master.php';
            if( file_exists($master) ){
                require_once( site_path() . '/app/views/master.php');
            }
        } else {
            die('Controller ''<em>' . $controller . '</em>'' doesn''t exists');
        }
    }
}

router.class.php

class Router extends Controller{
    public function get($uri = null, $ContollerMethod = null, $view = null){
        $permalink = get_permalink();
        if( $permalink == $uri and strtolower($_SERVER['REQUEST_METHOD']) == 'get' ){
            $this->render($ContollerMethod, $view);
        }
    }
    public function post($uri = null, $ContollerMethod = null, $view = null){
        $permalink = get_permalink();
        if( $permalink == $uri and strtolower($_SERVER['REQUEST_METHOD']) == 'post' ){
        }
    }
    public function ajax($uri = null, $ContollerMethod = null, $view = null){
        $permalink = get_permalink();
        if( $permalink == $uri and !empty($_SERVER['HTTP_X_REQUESTED_WITH']) && strtolower($_SERVER['HTTP_X_REQUESTED_WITH']) == 'xmlhttprequest'){
        }
    }
}
$router = new Router;

示例:

contactcontact/locations已在router.class.php中注册,因此没有问题,一切正常,但uri errorexample未注册,它应该显示视图中的404错误消息。

请帮忙。

基本解决方案(但不是最好的)是为Router::get()添加返回值(boolean)。如果处理了route,则返回的值为true;如果未处理,则返回false

router.php

// route handlers found
$founded = 0;
if( $router->get('', 'homeController@index', 'home') ){
    $founded++;
}
if( $router->get('contact', 'contactController@index', 'contact') ){
    $founded++;
}
if( $router->get('contact/locations', 'contactController@locations', 'contact') ){
    $founded++;
}
// no handlers found... the route is handled by error controller
if( $founded <= 0 ){
     $router->get('404', 'errorController@index', '404');
}

controller.class.php

class Router extends Controller{
    /**
    * Return true if a controller is found for handle the route
    * @return boolean
    */
    public function get($uri = null, $ContollerMethod = null, $view = null){
        $permalink = get_permalink();
        if( $permalink == $uri and strtolower($_SERVER['REQUEST_METHOD']) == 'get' ){
            return $this->render($ContollerMethod, $view); // return true if a controller and a view are found
       }
       return false; // added this line
    }
    //.............

controller::render() 中实现相同的loginc

controller.class.php

class Controller{
    /**
     * Return true if a controller is found
     * @return boolean
     */
    public function render($ContollerMethod = null, $view = null, $data = array() ){
        $controller = $this->controller($ContollerMethod);
        $method = $this->method($ContollerMethod);
        if( file_exists(site_path() . '/app/controllers/' . $controller . '.php') ){
            require_once(site_path() . '/app/controllers/' . $controller . '.php');
            if( !method_exists($controller, $method) ){
                die('No method ''<em>' . $method . '</em>'' exists on Controller ''<em>' . $controller . '</em>''');
            }
            $params = array();
            call_user_func_array( [$controller, $method], $params );
            $master = site_path() . '/app/views/master.php';
            if( file_exists($master) ){
                require_once( site_path() . '/app/views/master.php');
            }
            return true; // add this line
        } else {
            die('Controller ''<em>' . $controller . '</em>'' doesn''t exists');
        }
        return false; // add this line
    }
// .....................................

现在。。。我的两美分

在您的逻辑中,每次都会调用每个路由器,即使找到了控制器。一种优化是,如果找到控制器,则停止该过程,例如:

router.php

if( $router->get('', 'homeController@index', 'home') ){
    exit;
}
if( $router->get('contact', 'contactController@index', 'contact') ){
    exit;
}
if( $router->get('contact/locations', 'contactController@locations', 'contact') ){
     exit;
}
// no handlers found... the route is handled by error controller
$router->get('404', 'errorController@index', '404');

旁注:这是一个"意大利面条代码"解决方案,很抱歉我的英语很差:(