router.php 2.4 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394
  1. <?php
  2. /**
  3. * Functions for URL routing: given an URL, call the corresponding handler
  4. * function (the 'route' to the corresponding output).
  5. *
  6. * @author Taddeus Kroes
  7. * @version 1.0
  8. * @date 14-07-2012
  9. */
  10. namespace BasicWeb;
  11. require_once 'base.php';
  12. /**
  13. *
  14. *
  15. * <code>
  16. *
  17. * </code>
  18. *
  19. * @package BasicWeb
  20. */
  21. class Router extends Base {
  22. /**
  23. * The regex delimiter that is added to the begin and end of patterns.
  24. *
  25. * @var string
  26. */
  27. const DELIMITER = '%';
  28. /**
  29. * An associative array of regex patterns pointing to handler functions.
  30. *
  31. * @var array
  32. */
  33. private $routes = array();
  34. /**
  35. * Create a new Router instance.
  36. *
  37. * @param array $routes An initial list of routes to set.
  38. */
  39. function __construct(array $routes=array()) {
  40. foreach( $routes as $pattern => $handler )
  41. $this->add_route($pattern, $handler);
  42. }
  43. /**
  44. * Add a route as a (pattern, handler) pair.
  45. *
  46. * The pattern is regular expression pattern without delimiters. The
  47. * function adds '%^' at the begin and '$%' at the end of the pattern as
  48. * delimiters.
  49. *
  50. * The handler function must receive no arguments if the regex pattern
  51. * does not contain groups (which are contained in parentheses). If there
  52. * are groups, the matches for these are passed to the handler fucntion in
  53. * an array.
  54. *
  55. * @param string $pattern A regex pattern to mach URL's against.
  56. * @param mixed $handler The handler function to call when $pattern is matched.
  57. * @throws \InvalidArgumentException If $handler is not callable.
  58. */
  59. function add_route($pattern, $handler) {
  60. if( !is_callable($handler) )
  61. throw new \InvalidArgumentException(sprintf('Handler for patterns "%s" is not callable.', $pattern));
  62. $this->routes[self::DELIMITER.'^'.$pattern.'$'.self::DELIMITER] = $handler;
  63. }
  64. /**
  65. * Call the handler function corresponding to the specified url.
  66. *
  67. * If any groups are in the matched regex pattern, a list of matches is
  68. * passed to the handler function.
  69. *
  70. * @param string $url An url to match the saved patterns against.
  71. * @return mixed FALSE if no pattern was matched, the return value of the
  72. * corresponding handler function otherwise.
  73. */
  74. function call_handler($url) {
  75. foreach( $this->routes as $pattern => $handler ) {
  76. if( preg_match($pattern, $url, $matches) ) {
  77. array_shift($matches);
  78. return call_user_func_array($handler, $matches);
  79. }
  80. }
  81. return false;
  82. }
  83. }
  84. ?>