2
\$\begingroup\$

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 ;
}

}
\$\endgroup\$
0

1 Answer 1

3
\$\begingroup\$

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.

\$\endgroup\$

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Not the answer you're looking for? Browse other questions tagged or ask your own question.