Как расставить приоритеты в strpos, чтобы найти для меня наиболее точный результат - PullRequest
0 голосов
/ 09 мая 2018

У меня есть массив:

$array_of_routes = ['users/', 'articles/more', 'users/get', 'homepage/'];

И, например, у меня есть строка:

$route = "users/get/1"; 

Итак, я попытался найти его с помощью strpos, но поскольку «users /» является главой «users / get» в $ array_of_routes, я получаю взамен «users /», а не «users / get», это имеет смысл, потому что это то, что я просил сделать код.

Но есть ли способ приоритизировать или сделать результат более точным при попытке найти подстроку в строке?

Примечание: при удалении 'users /' из массива я получаю 'users / get'

Это мой код:

foreach($array_of_routes as $uri){
  if(strpos($current_uri, $uri) !== false)
    return $uri;

}

Спасибо вам за помощь!

Ответы [ 3 ]

0 голосов
/ 09 мая 2018

Вам нужно разбить $route и сопоставить его с наивысшей специфичностью, доступной в $array_of_routes

<?php
$array_of_routes = ['users', 'articles/more/', 'users/get', 'homepage'];
$route = "users/get/1/fgd/d/fg/";

// No reason to have trailing nor leading slashes or spaces; they are just noise
$array_of_routes = array_map(function($v){return trim(trim($v, '/'));}, $array_of_routes );
$route = trim(trim( $route, '/' ));

// Get the requested route pieces
$route_pieces = explode('/', $route);

// Make sure we loop enough times to account for all of the pieces
for($i = 0; $i<count($route_pieces); ++$i)
{
    // With each loop, build the route with one piece less and check if it exists in $array_of_routes
    if(in_array(implode('/', array_slice($route_pieces, 0, (count($route_pieces)-$i))), $array_of_routes))
    {
        echo 'Most specific route: '.implode('/', array_slice($route_pieces, 0, (count($route_pieces)-$i)));
        echo 'Arguments: '.implode('/', array_slice($route_pieces, (count($route_pieces)-$i)));
        break;
    }
}

Выход для $route = "users/get/1/fgd/d/fg/";:

Most specific route: users/get
Arguments: 1/fgd/d/fg
0 голосов
/ 09 мая 2018

Учитывая, что

2 маршрута A и B с одинаковым строковым префиксом могут быть одного уровня или разных уровней

пример 1) тот же уровень (префикс = /users/):

/users/get
/users/post

пример 2) разные уровни (префикс = /users):

/users/get
/users

мы можем сказать, что:

Храня маршруты в порядке «самый длинный-первый» , вы получаете следующее утверждение: 2 маршрута с одинаковым строковым префиксом и разными уровнями всегда сохраняются с более конкретным уровнем вначале.

Как получить:

$array_of_routes = ['users/', 'articles/more', 'users/get', 'homepage/', ...];

function sort_by_length($a,$b){
  return strlen($b)-strlen($a);
}

usort($array_of_routes,'sort_by_length');

function findRoute($current_uri){
  foreach($array_of_routes as $uri){
    if(strpos($current_uri, $uri) === 0){
      return $uri;
    }
  }
}

Примечание: функция strpos должна возвращать 0, в противном случае вы можете найти несколько неправильных маршрутов, соответствующих вашему URI.

0 голосов
/ 09 мая 2018

Легко!Сортируйте ваш массив так, чтобы пользователи / get находились перед пользователями /.Сделайте $array_of_routes = rsort($array_of_routes);

, это ставит ваши более длинные совпадения на первое место, и если ваш самый длинный элемент соответствует, функция возвращает.

...