Please consider the following very rudimentary “controllers” (for this function in this case (for simplicity):
function Index() { var_dump(__FUNCTION__); // show the "Index" page } function Send($n) { var_dump(__FUNCTION__, func_get_args()); // placeholder controller } function Receive($n) { var_dump(__FUNCTION__, func_get_args()); // placeholder controller } function Not_Found() { var_dump(__FUNCTION__); // show a "404 - Not Found" page }
And the following Route() function, based on a regular expression :
function Route($route, $function = null) { $result = rtrim(preg_replace('~/+~', '/', substr($_SERVER['PHP_SELF'], strlen($_SERVER['SCRIPT_NAME']))), '/'); if (preg_match('~' . rtrim(str_replace(array(':any', ':num'), array('[^/]+', '[0-9]+'), $route), '/') . '$~i', $result, $matches) > 0) { exit(call_user_func_array($function, array_slice($matches, 1))); } return false; }
Now I want to map the following URLs (trailing slashes are ignored) to the respective "controllers":
/index.php -> Index() /index.php/send/:NUM -> Send() /index.php/receive/:NUM -> Receive() /index.php/NON_EXISTENT -> Not_Found()
This is the part where everything starts to get complicated, I have two problems that I cannot solve ... I believe that I am not the first person to have this problem, so someone there must have a solution.
Catching 404 (allowed!)
I cannot find a way to distinguish between requests from root ( index.php ) and requests that should not exist as ( index.php/notHere ). Ultimately, I use the default index.php route for URLs that would otherwise have to be sent to the 404 - Not Found error page. How can i solve this?
EDIT - the solution just flashed in my mind:
Route('/send/(:num)', 'Send'); Route('/receive/(:num)', 'Receive'); Route('/:any', 'Not_Found'); // use :any here, see the problem bellow Route('/', 'Index');
Order Routes
If I configure the routes in a logical order, for example:
Route('/', 'Index'); Route('/send/(:num)', 'Send'); Route('/receive/(:num)', 'Receive'); Route(':any', 'Not_Found');
All URL requests are bound by the Index() controller, since an empty regular expression (remember: trailing slashes are ignored) matches all. However, if I define the routes in a "hacker" order, for example:
Route('/send/(:num)', 'Send'); Route('/receive/(:num)', 'Receive'); Route('/:any', 'Not_Found'); Route('/', 'Index');
Everything seems to work as it should. Is there an elegant way to solve this problem?
Routes cannot always be hardcoded (pulled out of the database or something else), and I need to make sure that it will not ignore any routes due to the order they determined. Any help is appreciated!