From: Danny van Kooten Date: Sun, 27 Nov 2011 15:56:57 +0000 (+0100) Subject: First commit X-Git-Tag: 1.0.0-alpha~37 X-Git-Url: http://git.osdn.net/view?a=commitdiff_plain;h=87cee4851b9537b8012c16613febbb3f32aa38d1;p=php-libraries%2FRouter.git First commit --- 87cee4851b9537b8012c16613febbb3f32aa38d1 diff --git a/.htaccess b/.htaccess new file mode 100644 index 0000000..fd91b23 --- /dev/null +++ b/.htaccess @@ -0,0 +1,3 @@ +Options +FollowSymLinks +RewriteEngine On +RewriteRule ^(.*)$ example.php [NC,L] \ No newline at end of file diff --git a/Router.php b/Router.php new file mode 100644 index 0000000..44dca8e --- /dev/null +++ b/Router.php @@ -0,0 +1,231 @@ +base_url = $base_url; + } + + /** + * Set the base url - gets prepended to all route url's. + * @param string $base_url + */ + public function setBaseUrl($base_url) { + $this->base_url = $base_url; + } + + /** + * Has a route been matched? + * @return boolean True if a route has been found, false if not. + */ + public function hasRoute() { + return $this->route_found; + } + + /** + * Get array with data of the matched route. + * @return array Array containing the controller, action and parameters of matched route. + */ + public function getRoute() { + return $this->route; + } + + + /** + * Match a route to the current REQUEST_URI. Returns true on succes (route matches), false on failure. + * + * @param string $route_url The URL of the route to match, must start with a leading slash. Dynamic URL value's must start with a colon. + * @param string $target The controller and action to map this route_url to, seperated by a hash (#). The action value defaults to 'index'. (optional) + * @param array $args Accepts two keys, 'via' and 'as'. 'via' accepts a comma seperated list of HTTP Methods for this route. 'as' accepts a string and will be used as the name of this route. + * @return boolean True if route matches URL, false if not. + */ + public function match($route_url, $target = '', array $args = array()) { + + // check if this is a named route, if so, store it. + if (isset($args['as'])) { + $this->named_routes[$args['as']] = $route_url; + } + + // check if a route has already been found + // if so, function doesn't have to run + if($this->route_found) return; + + // check for matching method + if (isset($args['via'])) { + + // all methods uppercase + $args['via'] = strtoupper($args['via']); + + // explode by comma + $request_methods = explode(',', $args['via']); + + // hack to simulate DELETE and PUT requests + if (isset($_POST['_method']) && ($_method = strtoupper($_POST['_method'])) && in_array($_method, array('PUT', 'DELETE'))) { + $server_request_method = $_method; + } else { + $server_request_method = $_SERVER['REQUEST_METHOD']; + } + + // check if current request has the right method for this route. if not, return false. + if (!in_array($_SERVER['REQUEST_METHOD'], $request_methods)) + return false; + } + + // check for matching URL + $request_url = parse_url($_SERVER['REQUEST_URI'], PHP_URL_PATH); + $request_url = rtrim($request_url, '/'); + + // setup route regex for route url + $route_regex = preg_replace("/:(\w+)/", "(\w+)", $this->base_url.$route_url); + + // check if request url matches route regex. if not, return false. + if (!preg_match("@^{$route_regex}*$@", $request_url, $matches)) + return false; + + // setup parameters + $params = array(); + + // fill params array + if (preg_match_all("/:(\w+)/", $route_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 => $name) { + if (isset($matches[$key + 1])) + $params[$name] = $matches[$key + 1]; + } + } + + if ($target) { + // target explicitly given + $target = explode('#', $target); + + $controller = $target[0]; + $action = (isset($target[1])) ? $target[1] : 'index'; + } else { + // target not explicitly given + // extract from url + $target = explode('/', $request_url); + + $controller = $target[0]; + $action = (isset($target[1])) ? $target[1] : 'index'; + } + + $this->route_found = true; + $this->route = array('controller' => $controller, 'action' => $action, 'params' => $params); + return true; + } + + /** + * Matches REST URL's for a given controller + * + * @param string $controller The controller name + * @param array $args Accepts 'only' and 'except' keys. If given, function only matches given methods (or excludes them, depending on what key you gave). + */ + public function resources($controller, array $args = array()) { + $routes = array( + 'index' => array($controller, "$controller#index", array('via' => 'GET')), + 'new' => array("$controller/new", "$controller#new", array('via' => 'GET')), + 'show' => array("$controller/:id", "$controller#show", array('via' => 'GET')), + 'edit' => array("$controller/:id/edit", "$controller#edit", array('via' => 'GET')), + 'update' => array("$controller/:id", "$controller#update", array('via' => 'PUT')), + 'destroy' => array("$controller/:id", "$controller#destroy", array('via' => 'DELETE')), + 'create' => array("$controller", "$controller#create", array('via' => 'POST')) + ); + + + if (isset($args['only'])) { + // only route to specified methods + $only = explode(',', $args['only']); + + foreach ($only as $o) { + if (isset($routes[$o])) + $this->match($routes[$o][0], $routes[$o][1], $routes[$o][2]); + } + + // abandon + return; + } elseif (isset($args['except'])) { + + $except = explode(',', $args['except']); + + // unset specified routes + foreach ($except as $e) { + unset($routes[$e]); + } + } + + // loop all routes + foreach ($routes as $r) { + $this->match($r[0], $r[1], $r[2]); + } + } + + /** + * 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 url_for_route($route_name,array $params = array()) { + // Check if route exists + if(!isset($this->named_routes[$route_name])) return false; + + $route_url = $this->named_routes[$route_name]; + + // replace route url with given parameters + if($params && preg_match_all("/:(\w+)/", $route_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 $i => $key) { + if (isset($params[$key])) + $route_url = preg_replace("/:(\w+)/",$params[$key],$route_url,1); + } + } + + return $route_url; + + } + + +} \ No newline at end of file diff --git a/example.php b/example.php new file mode 100644 index 0000000..4ce8d8a --- /dev/null +++ b/example.php @@ -0,0 +1,37 @@ +match('/','users#index'); + +// maps /user/5 to controller 'users', method 'show' with parameter 'id' => 5 +$r->match('/user/:id','users#show'); + +// maps POST request to /users/ to controller 'users' and method 'create' +$r->match('/users','users#create',array('via' => 'post')); + +// maps /photos/show to controller 'photos' and method 'show' +$r->match('/photos/show'); + +// maps /users/5/edit to controller 'users', method 'edit' with parameters 'id' => 5. +$r->match('/user/:id/edit','users#edit',array('via' => 'get', 'as' => 'user_edit_page')); + +// echoes /users/5/edit +echo $r->url_for_route('user_edit_page',array('id' => '5')); + + +if($r->hasRoute()) { + extract($r->getRoute()); + ?> +

Route found!

+

Controller:

+

Action:

+

Params:

+

No route found.