|
|
@@ -12,7 +12,7 @@ namespace webbasics;
|
|
|
require_once 'base.php';
|
|
|
|
|
|
/**
|
|
|
- * A Router is used to call a handler function with corresponding to an URL.
|
|
|
+ * A Router is used to call a handler with corresponding to an URL.
|
|
|
*
|
|
|
* Simple example: a website with the pages 'home' and 'contact'.
|
|
|
* <code>
|
|
|
@@ -33,9 +33,10 @@ require_once 'base.php';
|
|
|
* </code>
|
|
|
*
|
|
|
* You can use regular expression patterns to specify an URL. Any matches are
|
|
|
- * passed to the handler function as parameters:
|
|
|
+ * passed to the handler function in a single parameter:
|
|
|
* <code>
|
|
|
- * function page($pagename) {
|
|
|
+ * function page(array $data) {
|
|
|
+ * $pagename = $data[0];
|
|
|
* return "This is the $pagename page.";
|
|
|
* }
|
|
|
*
|
|
|
@@ -46,6 +47,26 @@ require_once 'base.php';
|
|
|
* $response = $router->callHandler('/contact'); // 'This is the contact page.'
|
|
|
* </code>
|
|
|
*
|
|
|
+ * Instead of functions, you can implement the RouteHandler interface in a
|
|
|
+ * handler class. The router will create an instance of the handler class and call *handleRequest*
|
|
|
+ * <code>
|
|
|
+ * class MyHandler implements RouteHandler {
|
|
|
+ * function handleRequest(array $data) {
|
|
|
+ * $pagename = $data[0];
|
|
|
+ * return "This is the $pagename page.";
|
|
|
+ * }
|
|
|
+ * }
|
|
|
+ *
|
|
|
+ * $router = new Router(array(
|
|
|
+ * '/(home|contact)' => 'MyHandler'
|
|
|
+ * ));
|
|
|
+ * $response = $router->callHandler('/home'); // 'This is the home page.'
|
|
|
+ * $response = $router->callHandler('/contact'); // 'This is the contact page.'
|
|
|
+ * </code>
|
|
|
+ *
|
|
|
+ * The WebBasics library provides a set of base handler classes implementing
|
|
|
+ * the RouteHandler interface. These are sufficient for most usage cases.
|
|
|
+ *
|
|
|
* @package WebBasics
|
|
|
*/
|
|
|
class Router extends Base {
|
|
|
@@ -84,12 +105,25 @@ class Router extends Base {
|
|
|
* parentheses), the matches for these are passed to the handler function.
|
|
|
*
|
|
|
* @param string $pattern A regex pattern to mach URL's against.
|
|
|
- * @param mixed $handler The handler function to call when $pattern is matched.
|
|
|
+ * @param RouteHandler|callable $handler The handler function to call when $pattern is matched.
|
|
|
* @throws \InvalidArgumentException If $handler is not callable.
|
|
|
*/
|
|
|
function addRoute($pattern, $handler) {
|
|
|
- if (!is_callable($handler))
|
|
|
- throw new \InvalidArgumentException(sprintf('Handler for patterns "%s" is not callable.', $pattern));
|
|
|
+ if (is_callable($handler)) {
|
|
|
+ $handler = array('callable', $handler);
|
|
|
+ } else if (!is_string($handler)) {
|
|
|
+ throw new \InvalidArgumentException('Handler should be callable or class name.');
|
|
|
+ } else if (!class_exists($handler)) {
|
|
|
+ throw new \InvalidArgumentException(sprintf(
|
|
|
+ 'Handler class "%s" does not exist.', $handler
|
|
|
+ ));
|
|
|
+ } else if (!in_array(__NAMESPACE__ . '\RouteHandler', class_implements($handler))) {
|
|
|
+ throw new \InvalidArgumentException(sprintf(
|
|
|
+ 'Handler class "%s" should implement the RouteHandler interface.', $handler
|
|
|
+ ));
|
|
|
+ } else {
|
|
|
+ $handler = array('class', $handler);
|
|
|
+ }
|
|
|
|
|
|
$this->routes[self::DELIMITER . '^' . $pattern . '$' . self::DELIMITER] = $handler;
|
|
|
}
|
|
|
@@ -108,10 +142,19 @@ class Router extends Base {
|
|
|
* corresponding handler function otherwise.
|
|
|
*/
|
|
|
function callHandler($url) {
|
|
|
- foreach ($this->routes as $pattern => $handler) {
|
|
|
+ foreach ($this->routes as $pattern => $tuple) {
|
|
|
if (preg_match($pattern, $url, $matches)) {
|
|
|
+ list($type, $handler) = $tuple;
|
|
|
array_shift($matches);
|
|
|
- $result = call_user_func_array($handler, $matches);
|
|
|
+
|
|
|
+ switch ($type) {
|
|
|
+ case 'callable':
|
|
|
+ $result = count($matches) ? $handler($matches) : $handler();
|
|
|
+ break;
|
|
|
+ case 'class':
|
|
|
+ $instance = new $handler;
|
|
|
+ $result = $instance->handleRequest($matches);
|
|
|
+ }
|
|
|
|
|
|
if ($result !== false)
|
|
|
return $result;
|
|
|
@@ -122,4 +165,20 @@ class Router extends Base {
|
|
|
}
|
|
|
}
|
|
|
|
|
|
+/**
|
|
|
+ * Interface for handler classes which can be bound to a router pattern.
|
|
|
+ *
|
|
|
+ * @package WebBasics
|
|
|
+ */
|
|
|
+interface RouteHandler {
|
|
|
+ /**
|
|
|
+ * Handle an HTTP request.
|
|
|
+ *
|
|
|
+ * @param string[] $data A list of matched pattern groups, without the zero-group.
|
|
|
+ * @return mixed FALSE if the handler function was not able to handle the
|
|
|
+ * request, else the result of the reqeust.
|
|
|
+ */
|
|
|
+ function handleRequest(array $data);
|
|
|
+}
|
|
|
+
|
|
|
?>
|