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 ;
}
}
1 Answer 1
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.
Explore related questions
See similar questions with these tags.