使用Regex匹配路由功能的url。无法让Regex工作

时间:2011-12-16 03:51:15

标签: php regex url-routing

我正在尝试构建一个路由器函数来正确匹配传入的URI,并将它们与存储系统URI的数组相匹配。我也有类似于CodeIgniter的通配符'(:any)'和'(:num)'。

基本上,我试图让'admin / stats /(:num)'条目在'admin / stats'和admin / stats / 1'上匹配。

当脚本启动时,我从一个单独的数组中获取所有路径并使用foreach来保存每个路径:

route('admin/stats/(:num)', array('#title' => 'Statistics',...));

功能是:

function route($path = NULL, $options = NULL) {

static $routes;

    //If no arguments are supplied, return all routes stored.
    if(!isset($path) && !isset($options)) {
        return $routes;
    }

    //return options for path if $path is set.
    if(isset($path) && !isset($options)) {

        //If we have an exact match, return it.
        if(array_key_exists($path, $routes)) {
            return $routes[$path];
        }
        //Else, we need to use RegEx to find the correct route options.
        else {
        $regex = str_replace('/', '\/', $path);
        $regex = '#^' . $regex . '\/?$#';
            //I am trying to get the array key for $route[$path], but it isn't working.

            // route_replace('admin/stats/(:num)') = 'admin/stats/([0-9]+)'.
        $uri_path = route_replace(key($routes[$path])); //route_replace replaces wildcards for regex.
            if(preg_match($regex, $uri_path)) {
                return $routes[$path];
            }
        }
    }

    $routes[$path] = $options;

    return $routes; 
}

路线替换功能:

function route_replace($path) {
    return str_replace(':any', '.+', str_replace(':num', '[0-9]+', $path));
}

$ routes数组中的键/值对如下所示:

[admin/stats/(:num)] => Array
    (
        [#title] => Statistics //Page title
        [#access] => user_access //function to check if user is authorized 
        [#content] => html_stats //function that returns HTML for the page
        [#form_submit] => form_stats //Function to handle POST submits.
    )

感谢您的帮助。这是我的第一台路由器,我对制作正确的Regex并不熟悉。

1 个答案:

答案 0 :(得分:1)

'admin / stats /(:num)'永远不会匹配'admin / stats',因为在你的“模式”中需要斜杠。在pseduo-regex中,您需要执行类似'admin / stats(/:num)'的操作。

您的代码中似乎也存在一些错误。这一行

$uri_path = route_replace(key($routes[$path]));
当$ path不是$ routes中存在的密钥时,

位于执行的块中。

我试图重写它,这似乎有用(这只是else子句):

foreach( array_keys( $routes ) as $route ) {
        $regex = '#^' . $route . '?$#';
        //I am trying to get the array key for $route'$path', but it isn't working.

        // route_replace('admin/stats/(:num)') = 'admin/stats/('0-9'+)'.
        $uri_path = route_replace($regex); //route_replace replaces wildcards for regex.
        if(preg_match($uri_path,$path)) {
            return $routes[$route];
        }
    }

但这需要'admin / stats /(:num)'为'admin / stats(/:num)'。

顺便说一句,如果你还没有,你应该得到一个调试器(Zend和xDebug是PHP最常见的两个)。它们在解决这类问题方面具有无可估量的价值。

另外,问问自己是否需要写一个路由器,或者你是否不能只使用其中一个非常好的路由器......