2024-08-14 07:11:36 +00:00
|
|
|
<?php
|
|
|
|
|
2024-11-29 16:21:08 +00:00
|
|
|
/**
|
2024-11-29 16:38:49 +00:00
|
|
|
* class Router
|
2024-11-29 16:21:08 +00:00
|
|
|
*
|
|
|
|
* A simple Router class to manage URL-to-callback mapping and dispatch requests to the appropriate controllers and methods.
|
|
|
|
* The class supports defining routes, matching URLs against patterns, and invoking callbacks for matched routes.
|
|
|
|
*/
|
2024-08-14 07:11:36 +00:00
|
|
|
class Router {
|
2024-11-29 16:21:08 +00:00
|
|
|
/**
|
|
|
|
* @var array $routes Associative array of route patterns and their corresponding callbacks.
|
|
|
|
*/
|
2024-08-14 07:11:36 +00:00
|
|
|
private $routes = [];
|
|
|
|
|
2024-11-29 16:21:08 +00:00
|
|
|
/**
|
|
|
|
* Adds a new route to the router.
|
|
|
|
*
|
|
|
|
* @param string $pattern The URL pattern to match (regular expression).
|
|
|
|
* @param string $callback The callback for the route in the format "Controller@Method".
|
|
|
|
*
|
|
|
|
* @return void
|
|
|
|
*/
|
2024-11-29 16:25:09 +00:00
|
|
|
public function add($pattern, $callback) {
|
2024-08-14 07:11:36 +00:00
|
|
|
$this->routes[$pattern] = $callback;
|
|
|
|
}
|
|
|
|
|
2024-11-29 16:21:08 +00:00
|
|
|
/**
|
|
|
|
* Dispatches a request to the appropriate route callback.
|
|
|
|
*
|
|
|
|
* @param string $url The URL to match against the defined routes.
|
|
|
|
*
|
|
|
|
* @return void Outputs the result of the invoked callback or a 404 error if no route matches.
|
|
|
|
*/
|
2024-08-14 07:11:36 +00:00
|
|
|
public function dispatch($url) {
|
2024-11-29 16:25:09 +00:00
|
|
|
// remove query string variables from url
|
2024-08-14 07:11:36 +00:00
|
|
|
$url = strtok($url, '?');
|
|
|
|
|
|
|
|
foreach ($this->routes as $pattern => $callback) {
|
2024-11-29 16:25:09 +00:00
|
|
|
// check if the URL matches the current route pattern
|
2024-08-14 07:11:36 +00:00
|
|
|
if (preg_match('#^' . $pattern . '$#', $url, $matches)) {
|
2024-11-29 16:25:09 +00:00
|
|
|
// remove the exact match to extrat parameters
|
2024-08-14 07:11:36 +00:00
|
|
|
array_shift($matches);
|
|
|
|
return $this->invoke($callback, $matches);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
// if there was no match at all, return 404
|
|
|
|
http_response_code(404);
|
|
|
|
echo '404 page not found';
|
|
|
|
}
|
|
|
|
|
2024-11-29 16:21:08 +00:00
|
|
|
/**
|
|
|
|
* Invokes the callback for a matched route.
|
|
|
|
*
|
|
|
|
* @param string $callback The callback for the route in the format "Controller@Method".
|
|
|
|
* @param array $params Parameters extracted from the route pattern.
|
|
|
|
*
|
|
|
|
* @return void Executes the specified method on the specified controller with the provided parameters.
|
|
|
|
*
|
|
|
|
* @throws Exception If the controller class or method does not exist.
|
|
|
|
*/
|
2024-08-14 07:11:36 +00:00
|
|
|
private function invoke($callback, $params) {
|
|
|
|
list($controllerName, $methodName) = explode('@', $callback);
|
2024-11-29 16:25:09 +00:00
|
|
|
$controllerClass = "../pages/$controllerName";
|
|
|
|
|
|
|
|
// ensure the controller class exists
|
|
|
|
if (!class_exists($controllerClass)) {
|
|
|
|
throw new Exception("Controller '$controllerClass' not found.");
|
|
|
|
}
|
|
|
|
|
2024-08-14 07:11:36 +00:00
|
|
|
$controller = new $controllerClass();
|
2024-11-29 16:25:09 +00:00
|
|
|
|
|
|
|
// ensure the method exists on the controller
|
|
|
|
if (!method_exists($controller, $methodName)) {
|
|
|
|
throw new Exception("Method '$methodName' not found in controller '$controllerClass'.");
|
|
|
|
}
|
|
|
|
|
|
|
|
// call the controller's method with the parameters
|
2024-08-14 07:11:36 +00:00
|
|
|
call_user_func_array([$controller, $methodName], $params);
|
|
|
|
}
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
?>
|