Last active
September 21, 2015 02:38
-
-
Save noodlehaus/3c6ddd6cc821617d8648 to your computer and use it in GitHub Desktop.
simple routing library with type hints
This file contains 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 | |
require __DIR__.'/routes.php'; | |
use badphp\routes\{ | |
function get, | |
function post, | |
function lookup | |
}; | |
# let's create some routes | |
$routes = []; | |
$routes[] = get('/index', function () { | |
return "Hello everyone!\n"; | |
}); | |
$routes[] = get('/welcome/<name>', function ($params) { | |
return "Welcome, {$params['name']}!\n"; | |
}); | |
$routes[] = post('/users', function () { | |
return "User created!\n"; | |
}); | |
# match request against routes | |
list($func, $params) = lookup($routes, $argv[1], $argv[2]); | |
if ($func === null) { | |
echo "Sorry, don't know what you mean!\n"; | |
exit; | |
} | |
# invoke matching action + args any way you like | |
echo $func($params); |
This file contains 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 | |
declare(strict_types=1); | |
namespace badphp\routes; | |
# get route mapper | |
function post(string $expr, callable $func): callable { | |
return route('POST', $expr, $func); | |
} | |
# get route mapper | |
function get(string $expr, callable $func): callable { | |
return route('GET', $expr, $func); | |
} | |
# get route mapper | |
function put(string $expr, callable $func): callable { | |
return route('PUT', $expr, $func); | |
} | |
# get route mapper | |
function delete(string $expr, callable $func): callable { | |
return route('DELETE', $expr, $func); | |
} | |
# creates a callable that ma | |
function route(string $verb, string $expr, callable $func): callable { | |
# create lambda that does the route matching | |
return function ($r_verb, $r_path) use ($verb, $expr, $func): array { | |
$r_verb = strtoupper(trim($r_verb)); | |
$r_path = trim($r_path, '/'); | |
# method mismatch | |
if ($r_verb !== strtoupper(trim($verb))) { | |
return [null, null]; | |
} | |
# match requested path against route, while picking out symbols | |
$expr = preg_replace( | |
['@<([^:]+)>@U', '@<([^:]+)(:(.+))?>@U'], | |
['<$1:[^/]+>', '(?<$1>$3)'], | |
trim($expr, '/') | |
); | |
# mismatch | |
if (!preg_match('@^'.$expr.'$@', $r_path, $params)) { | |
return [null, null]; | |
} | |
# process matched route symbols | |
$params = array_map('urldecode', array_intersect_key( | |
array_slice($params, 1), | |
array_flip(array_filter(array_keys($params), 'is_string')) | |
)); | |
return [$func, $params]; | |
}; | |
} | |
# looks up matching callable for method + path | |
function lookup(array $routes, string $verb, string $path): array { | |
# iterate over routes, and try to match the request | |
foreach ($routes as $route) { | |
list($func, $args) = $route($verb, $path); | |
if ($func !== null) { | |
return [$func, $args]; | |
} | |
} | |
# no matching route | |
return [null, null]; | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment