Я не знаю, охватит ли это все мыслимые случаи, но вы можете использовать preg_match_all
или preg_match
в отличие от итерации по шаблонам.Это также должно улучшить производительность.
Важно то, что важен порядок сопоставления (слева направо), с массивом и циклом вы не можете этого сделать (вы можете на самом деле, но это уродливее).Затем мы можем отсортировать маршруты по сложности, например:
//this is intentionally in the opposite order of what I want it.
$routes = ['definition' => ['\/', '\/admin\/user\/[a-z0-9]+\/']];
//the more / separators the closer to the beginning we want it. or the more complex regexs go first.
uasort($routes['definition'], function($a,$b){
//count the number of / in the route
//note the <=> spaceship (as it's called) is only available in PHP7+
return substr_count($b, '/') <=> substr_count($a, '/');
});
$url = '/admin/user/37/edit';
//in regex the pipe | is OR
preg_match('~^('.implode('|', $routes['definition']).')~i', $url, $matches);
print_r($matches);
Песочница
Вывод:
Array
(
[0] => Array
(
[0] => /admin/user/37/edit
)
[1] => Array
(
[0] => /admin/user/37/edit
)
)
Что правильно в этомдело.Даже если вы получите несколько совпадений, вы можете посчитать их длину strlen
и затем взять самое длинное или «лучшее» совпадение из них.Это довольно просто, используя strlen
и, возможно, сортировку по длине, поэтому я оставлю это на ваше усмотрение.
Однако я бы не назвал это гарантией того, что это будет работать 100% времени, это простоПервое, что пришло ко мне.
Другая идея
Другая идея - вы не привязываете совпадение к началу и концу строки.Теоретически, маршрут может / должен совпадать со всей строкой, как в моем примере выше, если вы добавите ^
и $
здесь:
preg_match('~^('.implode('|', $routes['definition']).')$~i', $url, $matches);
Это обеспечит полное совпадение и в этом случае ~\/~
не будет совпадать, даже если массив не отсортирован, как вы можете видеть в песочнице ниже.
Песочница
При этом не исключено, что вы будете иметь только / нужночастичное совпадение.Это зависит от вас и от того, как вы строите свои маршруты и URL-адреса.Конечно, вы можете просто использовать ^
start, как в начале, с типом совпадения, но вам нужно будет отсортировать их в этом случае.
Preg Match против Preg Match All
Предварительный матч также будет работать, но он вернет только первый матч.Так что, если он совпадает несколько раз, вы не можете сравнить их, чтобы найти лучший.Это может быть хорошо, если вы используете ^
и $
.
Надеюсь, это поможет.