1
1
<?php
2
+ namespace App ;
3
+
2
4
/**
3
5
* Router Class
4
6
* Set initial routes
5
7
* Take URI and call desired method
6
8
*/
7
9
class Router
8
10
{
9
- private $ routes = [
10
- 'GET ' => [],
11
- 'POST ' => []
12
- ];
11
+ private $ routes = [];
12
+ private $ params = [];
13
13
14
14
/**
15
- * Load routes.php file
15
+ * Method used to load routes.php file
16
16
* @param string $file Path to file
17
- * @return object Instance of router in order to use the other methods
17
+ * @return Router Instance of router in order to use the other methods
18
18
*/
19
- public static function load (string $ file )
19
+ public static function load (string $ file ) : Router
20
20
{
21
21
$ router = new static ;
22
22
@@ -26,65 +26,94 @@ public static function load(string $file)
26
26
}
27
27
28
28
/**
29
- * Register a GET route
30
- * @param string $uri Full route like 'task/add-task'
31
- * @param string $controller Controller and action, e.g: Task@add-task
29
+ * Register a route
30
+ * Process to convert the route (string) to a regular expression in order to have a more flexible router
31
+ * @param string $route Route string, either full route or regular expression
32
+ * @param array $params This array stores 'controller' and 'action of each route (if passed)
32
33
* @return void
33
34
*/
34
- public function get (string $ uri , string $ controller ) : void
35
+ public function addRoute (string $ route , array $ params = [] ) : void
35
36
{
36
- $ this ->routes ['GET ' ][$ uri ] = $ controller ;
37
+ // Escape forward slashes
38
+ $ route = preg_replace ('/\// ' , '\\/ ' , $ route );
39
+
40
+ // Convert variables e.g. {controller}
41
+ $ route = preg_replace ('/\{([a-z]+)\}/ ' , '(?P<1円>[a-z-]+) ' , $ route );
42
+
43
+ // Convert variables with custom regular expressions e.g. {id:\d+} for numbers
44
+ $ route = preg_replace ('/\{([a-z]+):([^\}]+)\}/ ' , '(?P<1円>2円) ' , $ route );
45
+
46
+ // Add start and end delimeter
47
+ $ route = '/^ ' . $ route . '$/i ' ;
48
+
49
+ $ this ->routes [$ route ] = $ params ;
37
50
}
38
51
39
52
/**
40
- * Register a POST route
53
+ * This is where you set the controller and action taken from the URI (like 'posts/add')
54
+ * ... and save those into $this->params
55
+ * This method is called in routes.php
41
56
* @param string $uri Full route like 'task/add-task'
42
- * @param string $controller Controller and action, e.g: Task@add-task
43
57
* @return void
44
58
*/
45
- public function post ( $ uri , $ controller ) : void
59
+ public function setParams ( string $ uri ) : void
46
60
{
47
- $ this ->routes ['POST ' ][$ uri ] = $ controller ;
61
+ // Store parameters for current 'controller' and 'action'
62
+ foreach ($ this ->routes as $ route => $ params )
63
+ {
64
+ if (preg_match ($ route , $ uri , $ matches ))
65
+ {
66
+
67
+ foreach ($ matches as $ key => $ match )
68
+ {
69
+ if (is_string ($ key ))
70
+ {
71
+ if ($ key === 'controller ' )
72
+ {
73
+ $ match = ucwords ($ match );
74
+ }
75
+
76
+ $ params [$ key ] = $ match ;
77
+ }
78
+ }
79
+
80
+ $ this ->params = $ params ;
81
+ }
82
+ }
48
83
}
49
84
50
85
/**
51
- * Load requested URI's associated controller method
52
- * @param string $uri Full route like 'task/add-task'
53
- * @param string $method GET or POST
54
- * @return void
86
+ * Call requested controller->action()
87
+ * At this point $this->params is = ['controller' => 'MyController', 'action' => 'desiredMethod', 'id' => 1]
88
+ * So first check if such 'controller' exists and 'action' is a callable method
89
+ * If so, then unset 'controller' and 'action', which leaves $this->params = ['id' => 1]
90
+ * And last, the desired function is called with all the parameters (array) like 'id'...
91
+ * ... and this can be used or not if the method doesn't receive any arguments
55
92
*/
56
- public function direct ( $ uri , $ method )
93
+ public function redirectTo () : void
57
94
{
58
- // Remove first part of URI which is 'php-basic-mvc'
59
- // Then, the string for the desired controller will be at 0 index
60
- array_shift ($ uri );
61
-
62
- if (empty ($ uri ))
95
+ $ controller = '\\Controllers \\' . $ this ->params ['controller ' ];
96
+ $ action = $ this ->params ['action ' ];
97
+
98
+ if (class_exists ($ controller ))
63
99
{
64
- return $ this -> callAction ( ' Index ' , ' get ' ) ;
65
- }
100
+ $ controller = new $ controller ;
101
+ unset( $ this -> params [ ' controller ' ]);
66
102
67
- if (array_key_exists ($ uri [0 ], $ this ->routes [$ method ]))
68
- {
69
- return $ this ->callAction (
70
- ...explode ('@ ' , $ this ->routes [$ method ][$ uri [0 ]])
71
- );
72
- }
103
+ if (is_callable ([$ controller , $ action ]))
104
+ {
105
+ unset($ this ->params ['action ' ]);
106
+ }
107
+ else
108
+ {
109
+ die ('Page not found. ' );
110
+ }
111
+ }
73
112
else
74
113
{
75
- return $ this ->callAction (
76
- ...explode ('@ ' , $ this ->routes [$ method ]['404 ' ])
77
- );
114
+ header ('location: ' . URLROOT );
78
115
}
79
-
80
- throw new Exception ('No route defined for this URI. ' );
81
- }
82
-
83
- private function callAction ($ controller , $ action )
84
- {
85
- $ controller = "Controllers \\{$ controller }" ;
86
- $ controller = new $ controller ;
87
116
88
- return $ controller-> $ action( );
117
+ call_user_func_array ([ $ controller, $ action], [ $ this -> params ] );
89
118
}
90
119
}
0 commit comments