OSDN Git Service

PSR-0 compliance
authorJefersson Nathan <admin@phpse.net>
Wed, 12 Feb 2014 11:54:10 +0000 (09:54 -0200)
committerJefersson Nathan <admin@phpse.net>
Wed, 12 Feb 2014 11:54:10 +0000 (09:54 -0200)
- 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 [changed mode: 0644->0755]
composer.json [new file with mode: 0755]
src/PHPRouter/Route.php [new file with mode: 0755]
src/PHPRouter/Router.php [new file with mode: 0755]

old mode 100644 (file)
new mode 100755 (executable)
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
+<?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.
diff --git a/composer.json b/composer.json
new file mode 100755 (executable)
index 0000000..e4e4cc2
--- /dev/null
@@ -0,0 +1,26 @@
+{\r
+    "name": "dannyvankooten/php-router",\r
+    "description": "Simple PHP Router, supports REST and reverse routing.",\r
+    "keywords": ["router", "routing", "php", "rest"],\r
+    "homepage": "https://github.com/dannyvankooten/PHP-Router",\r
+    "license": "MIT",\r
+    "authors": [\r
+        {\r
+            "name": "Danny van Kooten",\r
+            "email": "dannyvankooten@gmail.com",\r
+            "homepage": "http://dannyvankooten.com/"\r
+        },\r
+        {\r
+            "name": "Jefersson Nathan",\r
+            "email": "malukenho@phpse.net"\r
+        }\r
+    ],\r
+    "require": {\r
+        "php": ">=5.3.0"\r
+    },\r
+    "autoload": {\r
+        "psr-0": {\r
+            "PHProuter": "src/"\r
+        }\r
+    }\r
+}
\ No newline at end of file
diff --git a/src/PHPRouter/Route.php b/src/PHPRouter/Route.php
new file mode 100755 (executable)
index 0000000..bcaab03
--- /dev/null
@@ -0,0 +1,115 @@
+<?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;
+       }
+}
diff --git a/src/PHPRouter/Router.php b/src/PHPRouter/Router.php
new file mode 100755 (executable)
index 0000000..01e274b
--- /dev/null
@@ -0,0 +1,164 @@
+<?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