OSDN Git Service

Creating routes from YAML files. Closed #25
[php-libraries/Router.git] / src / PHPRouter / Router.php
1 <?php
2 namespace PHPRouter;
3
4 use Exception;
5 use PHPRouter\RouteCollection;
6
7 /**
8  * Routing class to match request URL's against given routes and map them to a controller action.
9  */
10 class Router
11 {
12     /**
13     * Array that holds all Route objects
14     * @var array
15     */ 
16     private $_routes = array();
17
18     /**
19      * Array to store named routes in, used for reverse routing.
20      * @var array 
21      */
22     private $_namedRoutes = array();
23
24     /**
25      * The base REQUEST_URI. Gets prepended to all route _url's.
26      * @var string
27      */
28     private $_basePath = '';
29
30     /**
31      * @param RouteCollection $collection
32      */
33     public function __construct(RouteCollection $collection)
34     {
35         $this->_routes = $collection;
36     }
37
38     /**
39      * Set the base _url - gets prepended to all route _url's.
40      * @param $basePath
41      */
42     public function setBasePath($basePath)
43     {
44         $this->_basePath = (string) $basePath;
45     }
46
47     /**
48     * Matches the current request against mapped routes
49     */
50     public function matchCurrentRequest()
51     {
52         $requestMethod = (isset($_POST['_method']) && ($_method = strtoupper($_POST['_method'])) && in_array($_method,array('PUT','DELETE'))) ? $_method : $_SERVER['REQUEST_METHOD'];
53         $requestUrl = $_SERVER['REQUEST_URI'];
54
55         // strip GET variables from URL
56         if (($pos = strpos($requestUrl, '?')) !== false) {
57             $requestUrl =  substr($requestUrl, 0, $pos);
58         }
59
60         return $this->match($requestUrl, $requestMethod);
61     }
62
63     /**
64      * Match given request _url and request method and see if a route has been defined for it
65      * If so, return route's target
66      * If called multiple times
67      *
68      * @param string $requestUrl
69      * @param string $requestMethod
70      * @return bool
71      */
72     public function match($requestUrl, $requestMethod = 'GET')
73     {
74         foreach ($this->_routes->all() as $routes) {
75
76             // compare server request method with route's allowed http methods
77             if (! in_array($requestMethod, (array) $routes->getMethods())) {
78                 continue;
79             }
80
81             // check if request _url matches route regex. if not, return false.
82             if (! preg_match("@^".$this->_basePath.$routes->getRegex()."*$@i", $requestUrl, $matches)) {
83                 continue;
84             }
85
86             $params = array();
87
88             if (preg_match_all("/:([\w-]+)/", $routes->getUrl(), $argument_keys)) {
89
90                 // grab array with matches
91                 $argument_keys = $argument_keys[1];
92
93                 // loop trough parameter names, store matching value in $params array
94                 foreach ($argument_keys as $key => $name) {
95                     if (isset($matches[$key + 1])) {
96                         $params[$name] = $matches[$key + 1];
97                     }
98                 }
99
100             }
101
102             $routes->setParameters($params);
103
104             return $routes;
105         }
106         return false;
107     }
108
109
110     /**
111      * Reverse route a named route
112      *
113      * @param $routeName
114      * @param array $params Optional array of parameters to use in URL
115      * @throws Exception
116      *
117      * @internal param string $route_name The name of the route to reverse route.
118      * @return string The url to the route
119      */
120     public function generate($routeName, array $params = array())
121     {
122         // Check if route exists
123         if (! isset($this->_namedRoutes[$routeName])) {
124             throw new Exception("No route with the name $routeName has been found.");
125         }
126
127         $route = $this->_namedRoutes[$routeName];
128         $url = $route->getUrl();
129
130         // replace route url with given parameters
131         if ($params && preg_match_all("/:(\w+)/", $url, $param_keys))
132         {
133
134             // grab array with matches
135             $param_keys = $param_keys[1];
136
137             // loop trough parameter names, store matching value in $params array
138             foreach ($param_keys as $key) {
139                 if (isset($params[$key]))
140                     $url = preg_replace("/:(\w+)/", $params[$key], $url, 1);
141             }
142         }
143         return $url;
144     }
145
146
147     /**
148      * Create routes by array, and return a Router object
149      *
150      * @param array $config provide by Config::loadFromFile()
151      * @return Router
152      */
153     public static function parseConfig(array $config)
154     {
155         $collection = new RouteCollection();
156         foreach ($config['routes'] as $name => $route) {
157             $collection->add($name, new Route($route[0], array(
158                 '_controller' => str_replace('.', '::', $route[1]),
159                 'methods' => $route[2]
160             )));
161         }
162
163         return new Router($collection);
164     }
165 }