1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
|
<?php
require_once('Controller.class.php');
class Router {
/**
* Array mapping URIs to controllers.
* A controller may register itself either by using
* Router::register($URI, $controller[, $function]);
* or by adding itself to the $ROUTER global.
*
* The default here just gives us a 404 handler.
*/
private $routes = array('/*' => 'Http404');
/**
* Instantiate a router that looks for controllers in $controllerpath.
*/
public function Router($controllerpath) {
// create a $ROUTES global that can be used to set up our
// $this->routes.
global $ROUTES;
$ROUTES = $this->routes;
// Split $controllerpath into directories, and load the
// controllers in each.
$dirs = explode(PATH_SEPARATOR, $controllerpath);
foreach ($dirs as $dir) {
// Find all files in $dir with the ext `.class.php'
$controllerfiles = glob($dir.'/*.class.php');
foreach ($controllerfiles as $file) {
// and include them
require_once($file);
}
}
$this->routes = $ROUTES;
unset($ROUTES);
}
/**
* Route the page at the relative URL $page to the appropriate
* controller, and call the appropriate function.
*/
public function route($page) {
$parts = explode('/', $page);
$length = count($parts); // the # of segments in $controllerpart
// if $page ends in "/", strip that off
if ($parts[$length-1]=='') {
array_pop($parts);
$length--;
}
$controllerpart = implode('/', $parts);
// Keep shortening $controllerpart until it matches something in
// $this->routes. The shortest it will ever become is '/*'.
// If no key exists for '/*', that's an infinite loop.
// Fortunately, the default value of $this->routes directs '/*'
// to the Http404 controller.
while(!isset($this->routes[$controllerpart])) {
$some_parts = array_slice($parts, 0, $length);
$controllerpart = implode('/', $some_parts).'/*';
$length--;
}
$length++;
// Figure what function to call on what controller
// Grammar Nazi Warning: `what' or `which'?
$controller = $this->routes[$controllerpart];
if (strpos($controller, '->')===false) {
// imply function
$function = $parts[$length];
} else {
preg_match('/(.*)->(.*)/', $controller, $matches);
$controller = $matches[1];
$function = $matches[2];
}
// Default to the `index' function, provided by all controllers
if ($function=='') {
$function = 'index';
}
// We will pass these arrays to the function.
$routed = array_slice($parts, 0, $length);
$remainder = array_slice($parts, $length);
// Finally, run the controller
$obj = new $controller();
if (in_array($function, get_class_methods($obj))) {
call_user_func(array($obj, $function),
$routed, $remainder);
} else {
$obj->http404($routed, $remainder);
}
}
/**
* This is to allow controllers to register themselves to the router.
* If $function=='', then the function will be determined by the segment
* to the right of the last segment in $path
*/
public static function register($path, $controller, $function='') {
$str = $controller.(($function=='')?'':'->'.$function);
global $ROUTES;
$ROUTES[$path] = $str;
}
}
|