* Dynamic URL's: use URL segments as parameters.
## Usage
+```php
+<?php
+require 'Router.php';
+require 'Route.php';
- <?php
- require 'Router.php';
- require 'Route.php';
+$router = new Router();
- $router = new Router();
+$router->setBasePath('/PHP-Router');
- $router->setBasePath('/PHP-Router');
+// defining routes can be as simple as this
+$router->map('/', 'users#index');
- // defining routes can be as simple as this
- $router->map('/', 'users#index');
+// or somewhat more complicated
+$router->map('/users/:id/edit/', array('controller' => 'SomeController', 'action' => 'someAction'), array('methods' => 'GET,PUT', 'name' => 'users_edit', 'filters' => array('id' => '(\d+)')));
- // or somewhat more complicated
- $router->map('/users/:id/edit/', array('controller' => 'SomeController', 'action' => 'someAction'), array('methods' => 'GET,PUT', 'name' => 'users_edit', 'filters' => array('id' => '(\d+)')));
+// You can even specify closures as the Route's target
+$router->map('/hello/:name', function($name) { echo "Hello $name."; });
- // You can even specify closures as the Route's target
- $router->map('/hello/:name', function($name) { echo "Hello $name."; });
-
- // match current request URL & http method
- $target = $router->matchCurrentRequest();
- var_dump($target);
-
- // generate an URL
- $router->generate('users_edit', array('id' => 5));
+// match current request URL & http method
+$target = $router->matchCurrentRequest();
+var_dump($target);
+// generate an URL
+$router->generate('users_edit', array('id' => 5));
+```
## More information
Have a look at the example.php file or read trough the class' documentation for a better understanding on how to use this class.
--- /dev/null
+<?php
+namespace PHPRouter;
+
+class Route
+{
+ /**
+ * URL of this Route
+ * @var string
+ */
+ private $_url;
+
+ /**
+ * Accepted HTTP methods for this route
+ * @var array
+ */
+ private $_methods = array('GET','POST','PUT','DELETE');
+
+ /**
+ * Target for this route, can be anything.
+ * @var mixed
+ */
+ private $_target;
+
+ /**
+ * The name of this route, used for reversed routing
+ * @var string
+ */
+ private $_name;
+
+ /**
+ * Custom parameter filters for this route
+ * @var array
+ */
+ private $_filters = array();
+
+ /**
+ * Array containing parameters passed through request URL
+ * @var array
+ */
+ private $_parameters = array();
+
+ public function getUrl()
+ {
+ return $this->_url;
+ }
+
+ public function setUrl($url)
+ {
+ $url = (string) $url;
+
+ // make sure that the URL is suffixed with a forward slash
+ if(substr($url,-1) !== '/') $url .= '/';
+
+ $this->_url = $url;
+ }
+
+ public function getTarget()
+ {
+ return $this->_target;
+ }
+
+ public function setTarget($target)
+ {
+ $this->_target = $target;
+ }
+
+ public function getMethods()
+ {
+ return $this->_methods;
+ }
+
+ public function setMethods(array $methods)
+ {
+ $this->_methods = $methods;
+ }
+
+ public function getName()
+ {
+ return $this->_name;
+ }
+
+ public function setName($name)
+ {
+ $this->_name = (string) $name;
+ }
+
+ public function setFilters(array $filters)
+ {
+ $this->_filters = $filters;
+ }
+
+ public function getRegex()
+ {
+ return preg_replace_callback("/:(\w+)/", array(&$this, 'substituteFilter'), $this->_url);
+ }
+
+ private function substituteFilter($matches)
+ {
+ if (isset($matches[1]) && isset($this->_filters[$matches[1]])) {
+ return $this->_filters[$matches[1]];
+ }
+
+ return "([\w-]+)";
+ }
+
+ public function getParameters()
+ {
+ return $this->_parameters;
+ }
+
+ public function setParameters(array $parameters)
+ {
+ $this->_parameters = $parameters;
+ }
+}
--- /dev/null
+<?php
+namespace PHPRouter;
+
+/**
+ * Routing class to match request URL's against given routes and map them to a controller action.
+ */
+class Router
+{
+ /**
+ * Array that holds all Route objects
+ * @var array
+ */
+ private $_routes = array();
+
+ /**
+ * Array to store named routes in, used for reverse routing.
+ * @var array
+ */
+ private $_namedRoutes = array();
+
+ /**
+ * The base REQUEST_URI. Gets prepended to all route _url's.
+ * @var string
+ */
+ private $_basePath = '';
+
+ /**
+ * Set the base _url - gets prepended to all route _url's.
+ * @param string $base_url
+ */
+ public function setBasePath($basePath)
+ {
+ $this->_basePath = (string) $basePath;
+ }
+
+ /**
+ * Route factory method
+ *
+ * Maps the given URL to the given target.
+ * @param string $routeUrl string
+ * @param mixed $target The target of this route. Can be anything. You'll have to provide your own method to turn * this into a filename, controller / action pair, etc..
+ * @param array $args Array of optional arguments.
+ */
+ public function map($routeUrl, $target = '', array $args = array())
+ {
+ $route = new Route();
+
+ $route->setUrl($this->_basePath . $routeUrl);
+
+ $route->setTarget($target);
+
+ if(isset($args['methods'])) {
+ $methods = explode(',', $args['methods']);
+ $route->setMethods($methods);
+ }
+
+ if(isset($args['filters'])) {
+ $route->setFilters($args['filters']);
+ }
+
+ if(isset($args['name'])) {
+ $route->setName($args['name']);
+ if (!isset($this->_namedRoutes[$route->getName()])) {
+ $this->_namedRoutes[$route->getName()] = $route;
+ }
+ }
+
+ $this->_routes[] = $route;
+ }
+
+ /**
+ * Matches the current request against mapped routes
+ */
+ public function matchCurrentRequest()
+ {
+ $requestMethod = (isset($_POST['_method']) && ($_method = strtoupper($_POST['_method'])) && in_array($_method,array('PUT','DELETE'))) ? $_method : $_SERVER['REQUEST_METHOD'];
+ $requestUrl = $_SERVER['REQUEST_URI'];
+
+ // strip GET variables from URL
+ if(($pos = strpos($requestUrl, '?')) !== false) {
+ $requestUrl = substr($requestUrl, 0, $pos);
+ }
+
+ return $this->match($requestUrl, $requestMethod);
+ }
+
+ /**
+ * Match given request _url and request method and see if a route has been defined for it
+ * If so, return route's target
+ * If called multiple times
+ */
+ public function match($requestUrl, $requestMethod = 'GET')
+ {
+
+ foreach ($this->_routes as $route) {
+
+ // compare server request method with route's allowed http methods
+ if (! in_array($requestMethod, $route->getMethods())) {
+ continue;
+ }
+
+ // check if request _url matches route regex. if not, return false.
+ if (! preg_match("@^".$route->getRegex()."*$@i", $requestUrl, $matches)) {
+ continue;
+ }
+
+ $params = array();
+
+ if (preg_match_all("/:([\w-]+)/", $route->getUrl(), $argument_keys)) {
+
+ // grab array with matches
+ $argument_keys = $argument_keys[1];
+
+ // loop trough parameter names, store matching value in $params array
+ foreach ($argument_keys as $key => $name) {
+ if (isset($matches[$key + 1])) {
+ $params[$name] = $matches[$key + 1];
+ }
+ }
+
+ }
+
+ $route->setParameters($params);
+
+ return $route;
+ }
+ return false;
+ }
+
+
+
+ /**
+ * Reverse route a named route
+ *
+ * @param string $route_name The name of the route to reverse route.
+ * @param array $params Optional array of parameters to use in URL
+ * @return string The url to the route
+ */
+ public function generate($routeName, array $params = array())
+ {
+ // Check if route exists
+ if (! isset($this->_namedRoutes[$routeName])) {
+ throw new Exception("No route with the name $routeName has been found.");
+ }
+
+ $route = $this->_namedRoutes[$routeName];
+ $url = $route->getUrl();
+
+ // replace route url with given parameters
+ if ($params && preg_match_all("/:(\w+)/", $url, $param_keys))
+ {
+
+ // grab array with matches
+ $param_keys = $param_keys[1];
+
+ // loop trough parameter names, store matching value in $params array
+ foreach ($param_keys as $key) {
+ if (isset($params[$key]))
+ $url = preg_replace("/:(\w+)/", $params[$key], $url, 1);
+ }
+ }
+ return $url;
+ }
+}
\ No newline at end of file