2016-04-03 3 views
0

Я работаю над своим мини-маршрутизатором url в PHP. До сих пор у меня есть регулярное выражение для извлечения переменных в URL, заключенной в {} (Глядя на маршрутизаторе код Symfony в):Regex для сопоставления маршрутов в PHP

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]; 
} 

Так что этот метод извлекает ВАР, теперь мне нужно регулярное выражение, чтобы соответствовать образцу маршрут с адресом. Я начал изучать регулярные выражения, но мне все же нехорошо обмануть голову.

+0

Таким образом, вы должны знать, как работает эта функция? Или вы хотите, чтобы другой набор регулярных выражений выполнял то, что вы хотите? Не совсем вам :) –

+0

Мне нужно другое regex :) Мне нужно создать регулярное выражение, чтобы я мог использовать его для сопоставления, поэтому, если у меня есть:/hello/{name}, метод пока извлекает только 'name' , но мне нужно создать регулярное выражение, которое будет соответствовать/привет/Сэм, я надеюсь, что в моем вопросе я буду ясно. –

+0

Вам нужно предоставить примеры URL-адресов. Также удалите тег маршрутизатора. – Laurel

ответ

0

Это будет работать: \/hello\/{?([^\/}]+)}?

(По крайней мере, это на примерах вы предоставили :)

/hello/{name} /hello/Sam

Объяснение

  • \/ является сбежавший /
  • hello находит hello, в случае, если вы этого не осознали.
  • {? находит {, если таковой имеется.
  • ([^\/}]+) находит все, что это не / или }
  • }? находит }, если есть один.
+0

Отлично работает, но ему нужно создать регулярное выражение для заданного шаблона. В зависимости от пути маршрута. Поэтому, если маршрут маршрута является/users/{user_id/posts, ему нужно будет сгенерировать что-то, что соответствует/users/5/posts, где 5 не нужно ограничивать числом. Кроме того, если другой маршрут маршрута является/articles/old/{article_id/он должен генерировать регулярное выражение, которое соответствовало бы/articles/old/50 –

+0

Я думаю, что я получил его, используя ваш ответ, регулярное выражение для/users/{user }/posts/{post} (route) users/Sam/posts/5 (url) будет \/users \/\ {? ([^ \ /}] +)}? \/posts \/{? ([^\ /}] +)}? и мне нужно использовать язык программирования для вычисления регулярного выражения –

0

Для всех, кому может быть интересно, я получил это, благодаря ответу Лорел.

Это обновленная версия методы он все еще нуждается в некоторой работе, хотя:

$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]; 
Смежные вопросы