Прежде всего вы должны определить свои маршруты немного более подробно. В противном случае неясно, как следует использовать заполнители в фигурных скобках. Конечно, вы, как программист, знаете, что для идентификатора должно быть числовое значение. Ваш валидатор может этого не знать.
Итак, давайте посмотрим, как вы можете определить свои маршруты немного более подробно.
$routes = [
[
'controller' => SomeController::class,
'route' => '/order/{id}',
'parameters' => [ 'id' => '([0-9a-z]+)' ],
'allowed_methods' => [ 'GET' ],
]
];
Это только примерная запись для маршрута , Маршрут содержит контроллер, который должен быть вызван, когда запрашивается этот маршрут. Также сам маршрут упоминается здесь. Кроме того, мы определяем параметр с именем id , который действует как заполнитель на вашем маршруте, и определяем разрешенные методы запроса. В этом случае маршрут должен быть доступен только через запросы GET. В нашем небольшом примере здесь нам просто нужны параметры и маршрут. Показанный ниже класс маршрутизатора не распознает метод запроса и контроллер.
Так как маршрут может быть разрешен и проверен? Все, что мы должны знать, теперь определено в маршруте. Когда происходит запрос, мы можем проверить маршрут.
Вот небольшой пример класса маршрутизатора. Конечно, этот небольшой пример не следует использовать для производства.
declare(strict_types=1);
namespace Marcel\Router;
class Router
{
protected array $routes = [];
protected array $filters = [];
public function __construct(array $routes)
{
$this->routes = $routes;
}
public function match(string $request) : bool
{
foreach ($this->routes as $route) {
// find parameters and filters (regex) in route
if (preg_match_all('/\{([\w\-%]+)\}/', $route['route'], $keys)) {
$keys = $keys[1];
}
foreach ($keys as $key => $name) {
if (isset($route['parameters'][$name])) {
$this->filters[$name] = $route['parameters'][$name];
}
}
// match requested route against defined route
$regex = preg_replace_callback('/\{(\w+)\}/', [ $this, 'substituteFilter' ], $route['route']);
$filter = rtrim($regex, '/');
$pattern = '@^' . $filter . '/?$@i';
// if not matching, check the next route
if (!preg_match($pattern, $request, $matches)) {
continue;
}
return true;
}
return false;
}
protected function substituteFilter(array $matches): string
{
if (isset($matches[1], $this->filters[$matches[1]])) {
return $this->filters[$matches[1]];
}
return '([\w\-%]+)';
}
}
Этот небольшой пример класса маршрутизатора проверяет данные URL-адреса на предмет совокупности маршрутов. Класс обращает внимание на заполнители, которые могут быть заполнены регулярным выражением. Таким образом, класс проверяет каждый запрос на соответствие регулярному выражению для данного заполнителя. Итак, давайте проверим этот маленький класс на некоторые запросы
$router = new Router($routes);
$result = $router->match('/order/BPQ123');
var_dump($result); // true
$result = $router->match('/bla/yadda/blubb');
var_dump($result); // false