Last active
July 29, 2016 10:57
-
-
Save DiyarD/e4c3c4b4d66cd2f10f8ffabe6bbfb6e2 to your computer and use it in GitHub Desktop.
A Very Simple PHP Router
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| <?php | |
| class Router | |
| { | |
| protected $_routes; | |
| protected $routeMethods = ['get', 'post']; | |
| public function add($pattern, $callback, $options) { | |
| $pattern = '/' . trim($pattern, '/'); | |
| $routerName = isset($options['name']) ? $options['name']: null; | |
| $type = isset($options['type']) ? strtolower($options['type']) : 'get'; | |
| if(!in_array($type, $this->routeMethods)) { | |
| throw new InvalidRequestMethodException("'{$type}' isn't a valid request type."); | |
| } | |
| $this->_routes[] = [ | |
| 'pretty' => $pattern, //The pretty dev-readable version of the route pattern eg : /users/{username} | |
| 'route' => $this->parseRoute($pattern), //The actual regex route pattern | |
| 'type' => $type, //the request method/type | |
| 'callback' => $callback, //the callback to be run if the route matches | |
| 'name' => $routerName, //the route name to be used in generateRoute() | |
| ]; | |
| } | |
| // Replaces the pretty placeholders with ugly regex | |
| public function parseRoute($pattern) { | |
| // Replace optional paramters eg( get('/users/{username}?') ) | |
| $pattern = preg_replace("/\/{[a-z]+}\?/", "(?:\/([a-zA-Z0-9-_.]*))?", $pattern); | |
| // Replace required parameters eg( get('/articles/{slug}') ) | |
| $pattern = preg_replace("/{[a-z]+}/", '([a-zA-Z0-9-_.]*)', $pattern); | |
| return $pattern; | |
| } | |
| public function run() { | |
| $url = isset($_GET['url']) ? '/' . trim(trim($_GET['url']), '/'): '/'; | |
| foreach($this->_routes as $route) { | |
| //check if the route pattern matches the url | |
| if(!preg_match("#^{$route['route']}$#", $url, $params)) { | |
| continue; | |
| } | |
| // check if the request is matching | |
| if(!$this->checkRouteMethod($route['type'])) { | |
| continue; | |
| } | |
| array_shift($params); | |
| if(is_callable($route['callback'])) { | |
| //calls the found route callback with the matched parameters | |
| return call_user_func_array($route['callback'], $params); | |
| } | |
| return new \Exception("Route callback isn't an instance of callable."); | |
| } | |
| // no routes matched | |
| header($_SERVER["SERVER_PROTOCOL"]." 404 Not Found", true, 404); | |
| die('<h1>404 - Page Not Found</h1>'); | |
| } | |
| // checks if the current request matches a routes required request type | |
| public function checkRouteMethod($type) { | |
| $requestType = strtolower($_SERVER['REQUEST_METHOD']); | |
| if(strtolower($type) == $requestType) { | |
| return true; | |
| } | |
| return false; | |
| } | |
| // finds a route by its name | |
| public function searchRoute($name) { | |
| foreach($this->_routes as $route) { | |
| if($route['name'] == $name) { | |
| return $route; | |
| } | |
| } | |
| return false; | |
| } | |
| // turns a route pattern into a uri with the given params (if any) | |
| public function generateRoute($routeName, $params = []) { | |
| $route = $this->searchRoute($routeName)['pretty']; | |
| if($params) { | |
| foreach($params as $name => $value) { | |
| $route = preg_replace("/{{$name}}\??/", $this->ceoEncode($value), $route); | |
| } | |
| } | |
| return $route; | |
| } | |
| // The following function was taken from a StackOverFlow post but I edited it. | |
| public function ceoEncode($string) { | |
| if(is_array($string)) { | |
| $encoded = []; | |
| foreach($string as $key => $value) { | |
| $encoded[$key] = $this->ceoEncode($value); | |
| } | |
| return $encoded; | |
| } | |
| //Clean up multiple dashes or whitespaces | |
| $string = preg_replace("/[\s-]+/", " ", $string); | |
| //Convert whitespaces to dash | |
| $string = preg_replace("/[\s]/", "-", $string); | |
| return $string; | |
| } | |
| } |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
NOTE: This an example of a router class and it isn't efficient, DON'T use that in a real world example ;)