Нужна помощь с поиском нестатических роутов
Ради обучения пишу свой мини mvc фреймворк. Щас на роутинге. Вот увидел как у симфони можно задать нестатический роут, сразу с доп регуляркой для параметра, и хочу реализовать подобное:
@Route("/test/foo/{slug}/bar/{id<\d+>}", name="test")
Тут, к примеру, нужно достать 2 параметра slug, id, для slug регулярка по умолчанию (напр. [a-zA-Z0-9]+), а для id та что в <>, тут будет \d+.
Роуты храню в таком виде:
$routes['get']['/contact'] = [MainController::class, 'contact'];
$routes['post']['/contact'] = [MainController::class, 'contact'];
$routes['get']['/articles/{slug}/comments/{id<\d+>}'] = [MainController::class, 'test'];
Статические роуты искать не проблема:
public function run() : Response
{
$method = $this->request->getMethod();
$path = $this->request->getPath();
$params = [];
$route = $this->routes[$method][$path] ?? false;
if (!$route) {
$route = $this->findUnstatic($this->routes[$method], $path, $params);
}
[$controller, $action] = $route;
$controllerInstance = new $controller();
return call_user_func([$controllerInstance, $action], $this->request , ...$params);
}
Нужна помощь с реализацией метода findUnstatic($routes, $path, &$params) {}, который вернет массив, где записан контроллер и метод для вызова, напр. [MainController::class, 'test'], если роут будет /articles/{slug}/comments/{id<\d+>}, а также запишет параметры slug, id в массив $params.
Ответы (1 шт):
Сделал сам свою задачу, правда не уверен в производительности такого варианта. Если ктото знает как можно улучшить, буду рад предложениям.
private function findUnstatic($routes, $path, &$params)
{
foreach ($routes as $route => $controller) {
if (preg_match($this->routeCompile($route), $path, $params)) {
array_shift($params);
return $controller;
}
}
return false;
}
private function routeCompile($route): string
{
$default = '(\w+)';
return preg_replace_callback('~{(.+?)}~', function ($match) use ($default) {
return preg_match('~<(.+?)>~', $match[1], $regex)? "($regex[1])" : $default;
}, "~^$route$~");
}