Good, flexible and secure MVC router PHP I have developed a new router after having learnt a lot from my previous attempts and I will be using this in sites I make from now on.

In a previous question, the issue of REQUEST_URI being too inflexible made me wonder if I could make adjustments to allow it to route $_POST and $_GET requests too?

Please let me know what you think and how it could be improved as I am still learning:



class Router {

public $offset = 9 ; // Adjust according to subdir length.
public $start_page = 'Index' ; // Change to your home/default page.
private $classAliases = array(
    'pretty-url' =&gt; 'UglyClassName',
) ;

private $methodAliases = array(
    'pretty-method' =&gt; 'uglyMethodName',
) ;

function __construct()
{
    $url = substr(rtrim($_SERVER['REQUEST_URI'], '/'), $this-&gt;offset) ;

    $command = explode('/', $url, 3) ;

    if(isset($command[0]))
    {
        $class = ucfirst($this-&gt;autoMap($command[0]), $this-&gt;classAliases) ;
    }

    if(class_exists($class) &amp;&amp; preg_match('/[^A-Za-z0-9]/', $class) == false)
    {
        $controller = new $class ;

        if($method = (isset($command[1]) ? $command[1] : NULL))
        {
            $method = (strstr($method, '?') ? substr($url, 0, strrpos($method, '?')) : $method) ;
            $method = $this-&gt;autoMap($method, $this-&gt;methodAliases) ;
            if(method_exists($class, $method) &amp;&amp; preg_match('/[^A-Za-z0-9]/', $method) == false)
            {
                $params = array() ;
                if(stristr($url, '?')) // Parameters passed the conventional way...
                {
                    $queryString = substr($url, strrpos($url, '?')+1) ;
                    parse_str($queryString, $params) ;
                }
                elseif(isset($command[2])) // ...or the clean URL way.
                {
                    $params = explode('/', $command[2]) ;
                }
                call_user_func_array(array($controller, $method), $params) ;
            }
            elseif($method)
            {
                $this-&gt;throwError('Method '.$method.' does not exist.') ;
            }
        } else { // Default index method.
            if(method_exists($class, 'index'))
            {
                $controller-&gt;index() ;
            } else {
                $this-&gt;throwError('Class '.$class.' has no index method.') ;
            }
        }
    }
    elseif(!$class)
    {
        $controller = new $this-&gt;start_page ;
        $controller-&gt;index() ;
    } else {
        $this-&gt;throwError('Class '.$class.' does not exist.') ;
    }
}

private function throwError($e)
{
    if(isset($_SERVER['HTTP_X_REQUESTED_WITH'])) // Ajax request...
    {
        echo $e ;
    } else { // ...or normal request.
        new Error($e) ;
    }
}

private function autoMap($alias, $routes)
{
    if(array_key_exists($alias, $routes))
    {
        return $routes[$alias] ;
    }
    return $alias ;
}

}
Where you have:


$class = ucfirst($this-&gt;autoMap($command[0]), $this-&gt;classAliases);



I think it should be:

$class = ucfirst($this-&gt;autoMap($command[0], $this-&gt;classAliases));


The closing ) is in the wrong place.

Besides that I like your router, maybe it would be even better if it had a module control (so you could have something like: module/controller/method). This way you can have separated modules for admin, debug, default, etc.