我正在用PHP开发我的迷你url路由器。到目前为止,我已经有了正则表达式,用于提取包含在{}中的url中的变量(通过查看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];
}
所以这个方法提取变量,现在我需要一个正则表达式来匹配路由的模式与 url。我开始学习正则表达式,但我仍然不太好理解这一点。
这将起作用: '/hello'/{?([^'/}]+)}?
(至少在您提供的示例上是这样:(
/hello/{name}
/hello/Sam
解释
-
'/
是逃脱的/
-
hello
找到hello
,以防你没有意识到。 -
{?
找到一个{
,如果有的话。 -
([^'/}]+)
找到所有不是/
或}
的东西 -
}?
找到一个}
,如果有的话。
对于任何可能感兴趣的人,我明白了,多亏了劳雷尔的回答。
这是该方法的更新版本,它仍然需要一些工作:
$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];