Skip to content

Instantly share code, notes, and snippets.

@jm42
Created August 16, 2016 23:30
Show Gist options
  • Save jm42/ac2d66bcf41a92729028a076d564b7f4 to your computer and use it in GitHub Desktop.
Save jm42/ac2d66bcf41a92729028a076d564b7f4 to your computer and use it in GitHub Desktop.
Bizarre implementation mixing FastRoute and my previous iteration
<?php
define('MATCH_ERR_OK', 0);
define('MATCH_ERR_NOT_FOUND', 1);
define('MATCH_ERR_METHOD_NOT_ALLOWED', 2);
function match(callable $handler): callable {
$static = $dynamic = ['GET' => [], 'POST' => []];
$routes = $handler(function(string $method, string $pattern) use(&$static, &$dynamic) {
$method = strtoupper($method);
if (!isset($static[$method])) { // or !isset($dynamic[$method])
throw new \InvalidArgumentException('Invalid method');
}
$id = uniqid();
if (preg_match_all('/\\(\\?P<(\w+)>[^\\)]+\\)/', $pattern, $matches)) {
$dynamic[$method][$pattern] = [$id, call_user_func_array('array_merge', array_slice($matches, 1))];
} else {
$static[$method][$pattern] = [$id];
}
return $id;
});
return function(string $method) use($routes, $static, $dynamic): callable {
$method = strtoupper($method);
if ($method === 'HEAD') {
$method = 'GET';
}
$varGroups = 0;
$patterns = [];
$datas = [];
foreach ($dynamic[$method] as $pattern => $data) {
$varCount = count($data[1]);
$varGroups = max($varGroups, $varCount);
$patterns[] = $pattern . str_repeat('()', $varGroups - $varCount);
$datas[++$varGroups] = $data;
}
$static = $static[$method];
$regex = '~^(?|' . implode('|', $patterns) . ')$~';
return function(string $path) use($routes, $static, $regex, $datas) {
if (isset($static[$path])) {
return ['error' => MATCH_ERR_OK, 'match' => $routes[$static[$path][0]]];
} elseif (preg_match($regex, $path, $matches)) {
list($id, $vars) = $datas[floor(count($matches) / 2) + 1];
$args = [];
foreach ($vars as $i => $var) {
$args[$var] = $matches[$i + 1];
}
return ['error' => MATCH_ERR_OK, 'match' => $routes[$id], 'args' => $args];
}
foreach ($routes as $prefix => $route) {
if (stristr($path, $prefix) === 0) {
$match = match($route)($req);
if ($match['error'] === MATCH_ERR_OK) {
return $match;
}
}
}
return ['error' => MATCH_ERR_NOT_FOUND];
};
};
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment