From ab305bbf8a72f673f0332714f56160c4ce718bcf Mon Sep 17 00:00:00 2001 From: Jefersson Nathan Date: Wed, 12 Feb 2014 09:54:10 -0200 Subject: [PATCH] PSR-0 compliance - Add namespaces for classes Router and Route. Now it is PHPRouter\Router and PHPRouter\Router. - Add autoload by PSR-0 compliance - Make small refactors on classes --- README.md | 36 +++++------ composer.json | 26 ++++++++ src/PHPRouter/Route.php | 115 +++++++++++++++++++++++++++++++++ src/PHPRouter/Router.php | 164 +++++++++++++++++++++++++++++++++++++++++++++++ 4 files changed, 323 insertions(+), 18 deletions(-) mode change 100644 => 100755 README.md create mode 100755 composer.json create mode 100755 src/PHPRouter/Route.php create mode 100755 src/PHPRouter/Router.php diff --git a/README.md b/README.md old mode 100644 new mode 100755 index c1d3dec..27fe907 --- a/README.md +++ b/README.md @@ -8,31 +8,31 @@ A simple Rails inspired PHP router class. * Dynamic URL's: use URL segments as parameters. ## Usage +```php +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. diff --git a/composer.json b/composer.json new file mode 100755 index 0000000..e4e4cc2 --- /dev/null +++ b/composer.json @@ -0,0 +1,26 @@ +{ + "name": "dannyvankooten/php-router", + "description": "Simple PHP Router, supports REST and reverse routing.", + "keywords": ["router", "routing", "php", "rest"], + "homepage": "https://github.com/dannyvankooten/PHP-Router", + "license": "MIT", + "authors": [ + { + "name": "Danny van Kooten", + "email": "dannyvankooten@gmail.com", + "homepage": "http://dannyvankooten.com/" + }, + { + "name": "Jefersson Nathan", + "email": "malukenho@phpse.net" + } + ], + "require": { + "php": ">=5.3.0" + }, + "autoload": { + "psr-0": { + "PHProuter": "src/" + } + } +} \ No newline at end of file diff --git a/src/PHPRouter/Route.php b/src/PHPRouter/Route.php new file mode 100755 index 0000000..bcaab03 --- /dev/null +++ b/src/PHPRouter/Route.php @@ -0,0 +1,115 @@ +_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; + } +} diff --git a/src/PHPRouter/Router.php b/src/PHPRouter/Router.php new file mode 100755 index 0000000..01e274b --- /dev/null +++ b/src/PHPRouter/Router.php @@ -0,0 +1,164 @@ +_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 -- 2.11.0