6 use Fig\Http\Message\RequestMethodInterface;
9 * Routing class to match request URL's against given routes and map
10 * them to a controller action.
15 * RouteCollection that holds all Route objects
17 * @var RouteCollection
19 private $routes = array();
22 * Array to store named routes in, used for reverse routing.
25 private $namedRoutes = array();
28 * The base REQUEST_URI. Gets prepended to all route url's.
31 private $basePath = '';
34 * @param RouteCollection $collection
36 public function __construct(RouteCollection $collection)
38 $this->routes = $collection;
40 foreach ($this->routes->all() as $route) {
41 $name = $route->getName();
43 $this->namedRoutes[$name] = $route;
48 private function getRequestUrlAndMethod()
51 isset($_POST['_method']) &&
52 ($_method = strtoupper($_POST['_method'])) &&
53 in_array($_method, array(RequestMethodInterface::METHOD_PUT, RequestMethodInterface::METHOD_DELETE), true)
54 ) ? $_method : $_SERVER['REQUEST_METHOD'];
56 $requestUrl = $_SERVER['REQUEST_URI'];
58 // strip GET variables from URL
59 if (($pos = strpos($requestUrl, '?')) !== false) {
60 $requestUrl = substr($requestUrl, 0, $pos);
70 * Set the base _url - gets prepended to all route _url's.
74 public function setBasePath($basePath)
76 $this->basePath = rtrim($basePath, '/');
80 * check if the request has a valid route
84 public function requestHasValidRoute()
86 list($requestMethod, $requestUrl) = $this->getRequestUrlAndMethod();
88 /** @var Route $route */
89 list($route,) = $this->findRoute($requestUrl, $requestMethod);
91 if ($route === null) {
95 $controller = $route->getValidController();
97 return $controller !== null;
101 * Matches the current request against mapped routes
103 public function matchCurrentRequest()
105 list($requestMethod, $requestUrl) = $this->getRequestUrlAndMethod();
107 return $this->match($requestUrl, $requestMethod);
110 private function findRoute($requestUrl, $requestMethod)
112 $currentDir = dirname($_SERVER['SCRIPT_NAME']);
116 // must be unit testing
117 if ($currentDir === "." || "..") {
121 foreach ($this->routes->all() as $routes) {
122 // compare server request method with route's allowed http methods
123 if (!in_array($requestMethod, (array)$routes->getMethods(), true)) {
127 if ('/' !== $currentDir) {
128 $requestUrl = str_replace($currentDir, '', $requestUrl);
131 $route = rtrim($routes->getRegex(), '/');
132 $pattern = '@^' . preg_quote($this->basePath) . $route . '/?$@i';
134 if (!preg_match($pattern, $requestUrl, $matches)) {
138 if (preg_match_all('/:([\w-%]+)/', $routes->getUrl(), $argument_keys)) {
139 // grab array with matches
140 $argument_keys = $argument_keys[1];
142 // check arguments number
144 if (count($argument_keys) !== (count($matches) - 1)) {
148 // loop trough parameter names, store matching value in $params array
149 foreach ($argument_keys as $key => $name) {
150 if (isset($matches[$key + 1])) {
151 $params[$name] = $matches[$key + 1];
156 $foundRoute = $routes;
160 /** @var Route $foundRoute */
161 /** @var array $params */
168 public function getRequestRoute()
170 list($requestMethod, $requestUrl) = $this->getRequestUrlAndMethod();
172 return $this->getRoute($requestUrl, $requestMethod);
175 public function getRoute($requestUrl, $requestMethod = RequestMethodInterface::METHOD_GET)
177 /** @var Route $route */
178 list($route, $params) = $this->findRoute($requestUrl, $requestMethod);
180 if ($route !== null) {
181 $route->setParameters($params);
190 * Match given request _url and request method and see if a route
191 * has been defined for it If so, return route's target If called
194 * @param string $requestUrl
195 * @param string $requestMethod
199 public function match($requestUrl, $requestMethod = RequestMethodInterface::METHOD_GET)
201 /** @var Route $route */
202 $route = $this->getRoute($requestUrl, $requestMethod);
204 if ($route !== null) {
205 return $route->dispatch();
207 throw new \DomainException("No route found for $requestMethod '$requestUrl'");
212 * Reverse route a named route
215 * @param array $params Optional array of parameters to use in URL
219 * @return string The url to the route
221 public function generate($routeName, array $params = array())
223 // Check if route exists
224 if (!isset($this->namedRoutes[$routeName])) {
225 throw new Exception("No route with the name $routeName has been found.");
228 /** @var \PHPRouter\Route $route */
229 $route = $this->namedRoutes[$routeName];
230 $url = $route->getUrl();
232 // replace route url with given parameters
233 if ($params && preg_match_all('/:(\w+)/', $url, $param_keys)) {
234 // grab array with matches
235 $param_keys = $param_keys[1];
237 // loop trough parameter names, store matching value in $params array
238 foreach ($param_keys as $key) {
239 if (isset($params[$key])) {
240 $url = preg_replace('/:' . preg_quote($key, '/') . '/', $params[$key], $url, 1);
249 * Create routes by array, and return a Router object
251 * @param array $config provide by Config::loadFromFile()
255 public static function parseConfig(array $config)
257 $collection = new RouteCollection();
258 foreach ($config['routes'] as $name => $route) {
259 $collection->attachRoute(new Route($route[0], array(
260 '_controller' => str_replace('.', '::', $route[1]),
261 'methods' => $route[2],
266 $router = new Router($collection);
267 if (isset($config['base_path'])) {
268 $router->setBasePath($config['base_path']);