简体   繁体   English

正则表达式用于PHP中的路由匹配

[英]Regex for route matching in PHP

I am working on my mini url router in PHP. 我正在用PHP开发迷你网址路由器。 So far I've got regex for extracting variables in the url enclosed in {}(By looking at Symfony's router code) : 到目前为止,我已经获得了正则表达式,用于提取{}中的网址中的变量(通过查看Symfony的路由器代码):

public function parse($pattern)
{
    $matches = '';
    $variables = array();
    $pos = 0;

    preg_match_all('#\{\w+\}#', $pattern, $matches, PREG_OFFSET_CAPTURE | PREG_SET_ORDER);

    foreach ($matches as $match) 
    {
        $varName = substr($match[0][0], 1, -1);

        if(is_numeric($varName)) {
            throw new Exception('Argument cannot be a number');
        }

        if (in_array($varName, $variables)) {
            throw new \LogicException(sprintf('More then one occurrence of variable name "%s".', $varName));
        }

        $variables[] = $varName;
    }

    return ['variables' => $variables];
}

So this method extracts the vars, now I need a regex to match the pattern of the route with the url. 因此,此方法提取了var,现在我需要一个正则表达式来匹配带有url的路由模式。 I started learning about regexes, but I still am not that good to wrap my head around this. 我开始学习有关正则表达式的知识,但我仍然不愿意为此做任何事情。

This will work: \\/hello\\/{?([^\\/}]+)}? 这将起作用: \\/hello\\/{?([^\\/}]+)}?

(At least it does on the examples you provided:) (至少在您提供的示例中如此:)

/hello/{name} /hello/Sam

Explanation 说明

  • \\/ is an escaped / \\/是一个转义的/
  • hello finds hello , in case you didn't realize. hello发现hello ,以防万一你没有意识到。
  • {? finds a { , if there is one. 找到{ ,如果有一个。
  • ([^\\/}]+) finds everything that's not a / or } ([^\\/}]+)查找不是/}
  • }? finds a } , if there is one. 找到一个} ,如果有的话。

For anyone that might be interested, I got it, thanks to Laurel's answer. 对于任何可能感兴趣的人,我都感谢劳雷尔的回答。

This is the updated version of the method it still needs some work though : 这是该方法的更新版本,但仍然需要一些工作:

$matches = '';
    $variables = array();
    $pos = 0;
    $reg = '#';
    $nextText = '';

    preg_match_all('#\{\w+\}#', $pattern, $matches, PREG_OFFSET_CAPTURE | PREG_SET_ORDER);

    foreach ($matches as $match) 
    {
        $varName = substr($match[0][0], 1, -1);
        $precedingText = substr($pattern, $pos, $match[0][1] - $pos);
        $pos = $match[0][1] + strlen($match[0][0]);
        $nxt = $pos - strlen($pattern);
        if($nxt == 0) $nxt = strlen($pattern); 
        $nextText = substr($pattern, $nxt);
        //$precedingText = substr($precedingText, 1, -1);
        $precSegments = explode('/', $precedingText);
        $precSegments = array_splice($precSegments, 1);
        //$temp = 5; 
        echo 'nxt ' . $nextText . '<><br>'; 
        if(strlen($precedingText) > 1)
        {       
            foreach($precSegments as $key => $value)
            {   
                $reg .= '\/';
                $reg .= $value; 
            }

            $reg .= '{?([^\/}]+)}?';  
        }
        else
        {
            $reg .= '{?([^\/}]+)}?';
        }

        $nextText = str_replace('/', '\/', $nextText);

        if(is_numeric($varName)) {
            throw new Exception('Argument cannot be a number');
        }

        if (in_array($varName, $variables)) {
            throw new \LogicException(sprintf('More then one occurrence of variable name "%s".', $varName));
        }

        $variables[] = $varName;    
    }

    if(count($matches) < 1)
    {
        $reg .= str_replace('/', '\/', $pattern);
    }

    $reg = $reg . $nextText;
    $reg .= '#';

    if($pattern == '/')
    {
        $reg = '#^[\/]+$#';
    }

    return ['variables' => $variables, 'regex' => $reg];

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM