Below is what I have come up with for a router/dispatcher system for my personal framework I am working on. Can you please review and tell me any improvements that could be made?
The first part is an array of URI -> to class/method/id_number/page_number using regex. I have only included a partial list of routes, there will be at least 50 possible routes that will have to run the regex on. I am thinking that is pretty bad for performance, but it seems the best way I know of to do it, since I need to match page numbers and id numbers when they exists.
I am new to MVC so this is my first attempt and I am sure you guys can give me improvement on this, thanks for any tips or help!
.htaccess
file:
RewriteEngine On
RewriteCond %{REQUEST_FILENAME} !-d
RewriteCond %{REQUEST_FILENAME} !-f
RewriteRule ^(.*)$ index.php?uri=$1 [NC,L,QSA]
Map array():
/**
* Map URI to class/method and ID and Page numbers
* Must be an array
*/
$uri_route_map = array(
//forums
'forums/' => array(
'controller' => 'forums',
'method' => 'index',
'id_number' => '',
'page_number' => ''),
'forums/viewforum/(?<id_number>\d+)' => array(
'controller' => 'forums',
'method' => 'viewforum',
'id_number' => isset($id_number),
'page_number' => ''),
'forums/viewthread/(?<id_number>\d+)' => array(
'controller' => 'forums',
'method' => 'viewthread',
'id_number' => isset($id_number),
'page_number' => ''),
'forums/viewthread/(?<id_number>\d+)/page-(?<page_number>\d+)' => array(
'controller' => 'forums',
'method' => 'viewthread',
'id_number' => isset($id_number),
'page_number' => isset($page_number)),
// user routes
// account routes
// blog routes
// mail routes
// various other routes
);
Router class that reads and matches the Map array above
/**
* Run URI against our Map array to get class/method/id-page numbers
*/
class Router
{
private $_controller = '';
private $_method = '';
public $page_number = '';
public $id_number = '';
public function __construct($uri, array $uri_route_map)
{
foreach ($uri_route_map as $rUri => $rRoute)
{
if (preg_match("#^{$rUri}$#Ui", $uri, $uri_digits))
{
//if page number and ID number in uri then set it locally
$this->page_number = (isset($uri_digits['page_number']) ? $uri_digits['page_number'] : null);
$this->id_number = (isset($uri_digits['id_number']) ? $uri_digits['id_number'] : null);
$this->_controller = $rRoute['controller'];
$this->_method = $rRoute['method'];
// just for debug and testing while working on it / will be removed from final code
echo '<hr> $page_number = ' . $this->page_number . '<br><br>';
echo '<hr> $id_number = ' . $this->id_number . '<br><br>';
echo '<hr> $controller = ' . $this->_controller . '<br><br>';
echo '<hr> $method = ' . $this->_method . '<br><br>';
break;
}else{
$this->page_number = '';
$this->id_number = '';
$this->_controller = '404';
$this->_method = '404';
}
}
}
public function getController()
{
return $this->_controller;
}
public function getMethod()
{
return $this->_method;
}
public function getPageNumber()
{
return $this->page_number;
}
public function getIDNumber()
{
return $this->id_number;
}
/**
* Call our class and method from values in the URI
*/
public function dispatch()
{
if (file_exists('controller' . $this->_controller . '.php'))
{
include ('controller' . $this->_controller . '.php');
$controllerName = 'Controller' . $this->_controller;
$controller = new $controllerName($this->getIDNumber(),$this->getPageNumber());
$method = $this->_method;
if (method_exists($this->_controller, $this->_method))
{
return $controller->$method();
} else {
// method does not exist
}
} else {
// Controller does not exist
}
}
}
Run it
/**
* Testing the class
*/
$uri = isset($_GET['uri']) ? $_GET['uri'] : null;
$router = new Router($uri, $uri_route_map);
$router->dispatch();
?>