Как проверить URL в массиве с помощью регулярных выражений в php? - PullRequest
0 голосов
/ 25 апреля 2020

Во-первых, я попробовал все вопросы и ответы, связанные с этим топи c. Кроме того, я попробовал связанные вопросы и попытался решить их, но безуспешно. Поэтому, пожалуйста, внимательно прочитайте мой вопрос.

Как проверить, что URL действителен в моих Маршрутах с использованием шаблонов Regex?

В этом коде пишется "Core PHP", а не в Framework.

$routes = [
          'PUT' =>
              [
               '/order/{id}' => 'updateOrder'
              ],
          'GET' =>
              [
                '/order' => 'getOrder',
                '/order/{id}' => 'getOrder',
                '/order/status/{id}' =>'getOrderStatus'
              ],
          'POST' =>
              [
               '/order' =>'createOrder'
              ],
          'DELETE' =>
              [
                 '/order/{id}' => 'deleteOrder'
              ]
        ];

Мой URL вроде:

1) '/ order / BPQ153'

2) '/ order / status / BPQ123'

3) '/ order'

Ответы [ 2 ]

2 голосов
/ 25 апреля 2020

Вы можете просто l oop по маршрутам и найти первый подходящий. Обратите внимание, что внешний l oop в приведенном ниже коде только потому, что я проверяю все примеры URL, которые вы указали сразу:

$routes = [
    'PUT' =>
        [
            '/order/{id}' => 'updateOrder'
        ],
    'GET' =>
        [
            '/order' => 'getOrder',
            '/order/{id}' => 'getOrder',
            '/order/status/{id}' => 'getOrderStatus'
        ],
    'POST' =>
        [
            '/order' => 'createOrder'
        ],
    'DELETE' =>
        [
            '/order/{id}' => 'deleteOrder'
        ]
];

$urlsToCheck = [
    '/order/BPQ153',
    '/order/status/BPQ123',
    '/order',
];

foreach ($urlsToCheck as $url) {
    foreach ($routes as $method => $methodValues) {
        foreach ($methodValues as $route => $function) {

            // match ID to everything that is not a slash
            $regex = str_replace('{id}', '([^\/]+)', $route);

            if (preg_match('@^' . $regex . '$@', $url)) {
                echo "The URL $url matches on $method HTTP method for function $function.";
                echo PHP_EOL;
            }
        }
    }
}

, это выдает:

The URL /order/BPQ153 matches on PUT HTTP method for function updateOrder.
The URL /order/BPQ153 matches on GET HTTP method for function getOrder.
The URL /order/BPQ153 matches on DELETE HTTP method for function deleteOrder.
The URL /order/status/BPQ123 matches on GET HTTP method for function getOrderStatus.
The URL /order matches on GET HTTP method for function getOrder.
The URL /order matches on POST HTTP method for function createOrder.

Как вы можете видите, я не проверял указанный HTTP-метод c, но вам нужно было бы добавить дополнительную проверку в зависимости от текущего используемого HTTP-метода. Однако это не было частью вопроса, поэтому я упоминаю здесь только для полноты.

PS: Для более чистого кода вы, конечно, можете поместить это в функцию / метод / класс, я просто попытался сохранить код как можно более короткий здесь.

1 голос
/ 25 апреля 2020

Прежде всего вы должны определить свои маршруты немного более подробно. В противном случае неясно, как следует использовать заполнители в фигурных скобках. Конечно, вы, как программист, знаете, что для идентификатора должно быть числовое значение. Ваш валидатор может этого не знать.

Итак, давайте посмотрим, как вы можете определить свои маршруты немного более подробно.

$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
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...