0

我正在构建一个 PHP 框架来结束我的课程,并且我坚持使用一个解决方案来匹配一些自定义路由和标准路由。

我的框架路线与 Zend Framework 1 的路线相似。

它与标准路线相匹配

/module/controller/action/param/value/param2/value2/paramn/valuen

URI 部分是可选的,/ 路由指向应用程序模块、索引控制器和索引操作,没有参数和值。

我被困在一些自定义路线中,我是这样定义的:

/blog/:postname/
/admin/logout/
/blog/posts/:year/:category/
/about/

该路由必须与此示例 URI 请求匹配。

/blog/my-first-post/
/blog/my-first-post/referenced/facebook/
/admin/logout/
/admin/logout/session-id/246753/action
/blog/posts/2013/turism/
/blog/posts/2013/turism/page/2/

但不必匹配标准路线。自定义路由必须在标准路由之前。标准路线的一些示例。例子:

/
/application/
/application/index/
/application/index/index/
/blog/posts/view/id/3/
/admin/login/
/admin/login/logout (that one are the 
/admin/blog/posts/edit/id/3/
/admin/blog/posts/edit/id/3/success/false/

我发现优雅地做到这一点的方法是使用 RegEx 进行比赛,但我已经尝试学习 RegEx 一个多月了,但并没有完全掌握。

PS:匹配当前路由后,我必须将 :variable 与 REQUEST_URI 中的相关位置绑定。

谢谢你的帮助。

4

2 回答 2

0

虽然很诱人,但在这种特殊情况下,我不会使用正则表达式。尽管我通常是这样走的。一个简单的循环和匹配就可以了,除非你的课程设置了一些你必须遵循的限制。

我整理了一个应该完成工作并在控制台中运行的示例,只是为了说明我的意思。

function get_route($uri){
  $routes = [
    'blog#show' => 'blog/:postname',
    'admin#logout' => 'admin/logout',
    'blog#category' => 'blog/posts/:year/:category',
    'home#about' => 'about'
  ];

  $params = [];

  $uri = preg_replace('/#|\?.+/', '', $uri); // remove hash or query strings
  $uri = preg_replace('/(^\/)?(\/$)?/', '', $uri); // trim slashes
  $uri = explode('/', $uri);
  $action = null;
  foreach ($routes as $this_action => $this_route) { // loop through possible routes
    $fractions = explode('/', $this_route);
    if (sizeof($fractions) !== sizeof($uri)) continue; // did not match length of uri
    for ($i=0; $i<sizeof($uri); $i++) { // compare each part of uri to each part of route
      if (substr($fractions[$i], 0, 1) !== ':' && $fractions[$i] !== $uri[$i]) break; // not a match and not a param
      if ($i === sizeof($uri)-1) { // made it to the last fraction!
        $ii = 0;
        foreach ($fractions as $fraction) {
          if (substr($fraction, 0, 1) == ':') { // it's a param, map it!
            $params[substr($fraction,1)] = $uri[$ii];
          }
          $ii++;
        }

        return ['action'=>$this_action, 'params'=>$params];
      }
    }
  }
  return false;
}
于 2013-11-07T22:26:01.097 回答
0

我可以用这段代码来满足我的需求,已经通过了很多测试。

public function matchCustomRoute($uri)
{
    if($uri == '')
    {
        return null;
    }

    $customRoutes = $this->getRoutes();

    $explodeUri = explode('/', $uri);
    $arrayUri = array();
    foreach($explodeUri as $uriPart)
    {
        if($uriPart == '')
        {
            continue;
        }
        $arrayUri[] = $uriPart;
    }
    $countUri = count($arrayUri);


    foreach($customRoutes as $key => $value)
    {

        $explodeRoute = explode('/',$value['route']);
        $arrayRoute = array();
        foreach($explodeRoute as $routePart)
        {
            if($routePart == '')
            {
                continue;
            }
            $arrayRoute[] = $routePart;
        }
        $countRoute = count($arrayRoute);
        if($countRoute > $countUri)
        {
            continue;
        }
        $matches = 0;

        for($i = 0 ; $i < $countRoute ; $i++)
        {
            $match = preg_match('/'.$arrayUri[$i].'/', '/'.$arrayRoute[$i].'/');
            if($match == 0)
            {
                if(substr($arrayRoute[$i], 0, 1) == ':')
                {
                    $value['params'][substr($arrayRoute[$i], 1)] = $arrayUri[$i];
                }
                else
                {
                    continue;
                }
            }
            $matches++;

        }
        if($matches == $countRoute)
        {
            return $value;
        }

    }
    return null;
}

谢谢你的帮助。

于 2013-11-08T13:35:29.103 回答