如何使正则表达式变量捕获路由

时间:2011-11-12 01:36:44

标签: php regex url routing sinatra

任何人都可以帮我解决这个问题。

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 个答案:

答案 0 :(得分: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'];