# 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' => 'UglyClassName', ) ; private$methodAliases = array(
'pretty-method' => 'uglyMethodName',
) ;

function __construct()
{
$url = substr(rtrim($_SERVER['REQUEST_URI'], '/'), $this->offset) ;$command = explode('/', $url, 3) ; if(isset($command[0]))
{
$class = ucfirst($this->autoMap($command[0]),$this->classAliases) ;
}

if(class_exists($class) && 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->autoMap($method,$this->methodAliases) ;
if(method_exists($class,$method) && 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->throwError('Method '.$method.' does not exist.') ; } } else { // Default index method. if(method_exists($class, 'index'))
{
$controller->index() ; } else {$this->throwError('Class '.$class.' has no index method.') ; } } } elseif(!$class)
{
$controller = new$this->start_page ;
$controller->index() ; } else {$this->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 ;
}

}

-
add comment

## 1 Answer

Where you have: $class = ucfirst($this->autoMap($command[0]),$this->classAliases);

I think it should be: $class = ucfirst($this->autoMap($command[0],$this->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.

-
add comment