This repository has been archived by the owner on Oct 23, 2020. It is now read-only.
-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathrouter.php
148 lines (121 loc) · 3.85 KB
/
router.php
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
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
<?php
/**
* Contains MVC_Router class
*/
namespace SmallPHPMVC;
/**
* Routes the execution of a page load to the appropreate controller method, based
* on GET parameters.
*
* @author David Lancea
*/
Class Router {
protected $get_var_name = 'url';
protected $controller_path = 'controller/';
/**
* Constructor
*
*/
function __construct($options = array()) {
$this->get_var_name = $options['get_var_name'] ?: $this->get_var_name;
$this->controller_path = $options['controller_path'] ?: $this->controller_path;
}
/**
* Set path to controllers. Default is ./controller/
* @param type $path
*/
function setPath($path) {
$path = rtrim($path, '/\\');
$path .= DIRSEP;
if ( !is_dir($path) ) {
throw new \Exception('Invalid controller path: `' . $path . '`');
}
$this->controller_path = $path;
}
/**
* Determine the controller and action path, then load and execute that action, passing
* any additional vairables to it.
*
*/
function delegate() {
// Analyze route
$route = $this->decodeRoute( $_GET[$this->get_var_name] );
// File available?
if (is_readable($route['file']) == false) {
$this->notFound('no-file');
}
// Always include base controller
require_once($this->controller_path . 'app.php');
// Include the file
include_once($route['file']);
// Initiate the class
$class = 'Controller\\' . $route['controller'];
$controller_obj = new $class();
// Action available?
if (is_callable(array ($controller_obj, $route['action'] )) == false) {
$this->notFound('no-action');
}
// Check for number of arguments
$method = new \ReflectionMethod($controller_obj, $route['action']);
$number_of_args = count($route['additional_arguments']);
if( $number_of_args < $method->getNumberOfRequiredParameters() ){
throw new Exception('Not enough arguments given to controller. ' . $method->getNumberOfRequiredParameters() . ' required.');
}
if( $number_of_args > $method->getNumberOfParameters() ){
throw new Exception('Too many arguments given to controller. ' . $method->getNumberOfParameters() . ' expected.');
}
// Run action, esentailly does this: $controller_obj->$route['action']($args[0], $args[1], ...);
call_user_func_array(array($controller_obj, $route['action']), $route['additional_arguments']);
}
/**
* Used to determine controller file, controller name, action name, and additional arguments
* for requested URL
*
* @param string A partial URI for a controller, action, and additional parameters separated by
* forward slashes. Example: controller/action/param1/param2
* @return array Associative array containing:
* 'file', 'controller', 'action', 'additional_arguments'
*/
private function decodeRoute($route) {
// Get separate parts
$route = trim($route, '/\\');
$parts = explode('/', $route);
// Controller might be in a subdirectory of controller dir. This will search down the
// array of routing "parts" till it either finds a matching file
$current_path = $this->controller_path;
$controller = '';
foreach ($parts as $part) {
$fullpath = $current_path . $part;
// Is there a dir with this path?
if (is_dir($fullpath)) {
$current_path .= $part . DIRSEP;
array_shift($parts);
continue;
}
// Find the file
if (is_file($fullpath . '.php')) {
$controller = $part;
array_shift($parts);
break;
}
}
// Get action
$action = array_shift($parts);
// Set default $controller to index
if(!$controller)
$controller = 'index';
// Set default $action to index
if(!$action)
$action = 'index';
$args = $parts;
$return['controller'] = $controller;
$return['action'] = $action;
$return['additional_arguments'] = $parts;
$return['file'] = $current_path . $controller . '.php';
return $return;
}
private function notFound() {
header('HTTP/1.1 404 Not Found');
// die("404 Not Found");
}
}