Как создать переменные регулярных выражений для захвата маршрутов

#php #regex #url #routing #sinatra

#php #регулярное выражение #url #маршруты #синатра

Вопрос:

любой может помочь мне с этой проблемой.

 example $uri = '/username/carlos'; => $routes[] = '/username/@name';
  

преобразование @name в переменную $name с захватом строки «carlos»

 $routes[] = '/list/edit/@id:[0-9]{3}';

$routes[] = '/username/@name';

$routes[] = '/archive/*';

$routes[] = '/';


$uri = '/username/carlos';

foreach ( $routes as $pattern )
{
    if ( preg_match( '#^' . preg_replace( '#(?:{{)?@(w b)(?:}})?#i', '(?P<1>[w-.!~*'"(),s] )',
                            str_replace( '*', '(.*)', preg_quote( $pattern, '/' ) ) ) . '/?$#i', $uri, $matchs ) )
    {

        //how to make regex for this to work :


        echo $name; // carlos =>$uri = '/username/carlos'; or matt => $uri = '/username/matt';

    }
}
  

спасибо за чтение

Комментарии:

1. Почему бы вам не использовать готовый фреймворк маршрутизации? И не следует ли вам сначала разбить часть преобразования вложенного шаблона, чтобы отладить ее?

Ответ №1:

Вам нужно было бы проделать гораздо больше работы, чтобы заставить это работать, в первую очередь для преобразования маршрута в регулярные выражения, которые вы затем можете использовать в заданном URI. Я бы сделал это следующим образом

 $routes = $params = array();

$routes[] = '/list/edit/@id:[0-9]{3}';
$routes[] = '/username/@name';
$routes[] = '/archive/*';
$routes[] = '/';

$uri = '/username/carlos';

foreach($routes as $pattern) {
    // Convert all characters into safe characters
    $pattern = preg_quote($pattern, '~');

    // Convert * into .*?
    $pattern = preg_replace('/(?<!\\)\\*/', '.*?', $pattern);

    #echo '<pre>'.print_r($pattern, true).'</pre>';
    // Convert any @name:expression into their expressions for capture
    $pattern = preg_replace_callback('%@([a-zA-Z] )(\\:([^/] ))?%', 'regex_callback', $pattern);

    $pattern = '~^' . $pattern . '$~';

    if(preg_match($pattern, $uri, $matches)) {
        $params = $matches;
        break;
    }
}

echo '<pre>'.print_r($params, true).'</pre>';

function regex_callback($data) {
    #echo '<pre>'.print_r($data, true).'</pre>';
    $pattern = '[^/] ';
    if(!empty($data[3])) {
        $pattern = stripslashes($data[3]);
    }
    return '(?P<' . $data[1] . '>' . $pattern . ')';
}
  

Он преобразует * в .*? , а затем преобразует @param в (?P<param>[^/] ) или заменяет [^/] выражение после :

Если совпадение найдено, оно присваивает совпадениям значение $params и завершает цикл foreach. Чтобы найти имя, вам тогда просто нужно было бы использовать

 echo $param['name'];
  

Комментарии:

1. Привет, как использовать регулярное выражение для $uri = ‘/list/edit/123.html ‘; с помощью $routes[] = ‘/list/edit/@id:[0-9]{3}.html’; результат «123.html «но не работает single var «123» извините за мой английский!

2. Вы могли бы просто использовать basename вместо этого, чтобы получить это. php.net/basename