RegExp语言路由

时间:2014-09-30 17:43:16

标签: php regex routes preg-match-all

美好的一天,

我需要基于网站客户端语言的Route-RegExp。 它应该是这样的:

Relative URL / Route:
/(No-Language) -> /?lng=(someDefaultLanguage)
/(No-Language)/ -> /?lng=(someDefaultLanguage)
/lngCode/page -> /page/?lng=lngCode
/lngCode/page/ -> /page/?lng=lngCode
/lngCode/pageL1/pageL2 -> /pageL1/pageL2/?lng=lngCode
/language/page?param=Value -> /page/?lng=lngCode&param=Value

(注意某些行上的尾部斜杠)

树结构是......无限的:)

有一些URL-Params的单个和多个。

我绝对没有正则表达式向导,我在uhm中管理了这个结果,......小时:

/^\/([a-z]{2})(?:(.*[^\?])|^$)((?:[\/\?]).*|^$)/

请不要问我在那里尝试的路线。我是正则表达式的新手。 提前谢谢

-

编辑澄清(我希望):

基本上就是这个概念:(如果我没有提及,它是内部路由,没有重定向。) 必须从第一个URL抓取语言参数(作为目录样式)并附加为名为“lng”的真实参数。 directory-parameter应该会消失。 如果已经存在其他参数,则还需要附加它们(?/& -case)。 如果没有给出语言(= default-language),则url中没有directory-style-parameter。如果仍然可以附加?lng = en参数,那就太好了。

示例:

localhost/blogpage/coolentry (default language)

localhost/de/blogpage/coolentry

localhost/es/blogpage/coolentry

localhost/blogpage/ -> localhost/blogpage/?lng=en

localhostde/de/blogpage/ -> localhost/blogpage/?lng=de

localhost/blogpage/coolentry/ -> localhost/blogpage/coolentry/?lng=en

localhost/de/blogpage/coolentry/ -> localhost/blogpage/coolentry/?lng=de

localhost/de/blogpage/coolentry/?entryPage=1 -> localhost/blogpage/coolentry/?lng=de&entryPage=1

它始终使用真实的语言参数进行路由。 我还编辑了第一篇文章,其中有一个令人困惑的错字。

1 个答案:

答案 0 :(得分:0)

对不起延迟@hcm 好吧,我得告诉你。我花了10分钟写了原始的正则表达式 在Perl中测试过,一切都很顺利。

然后我将它转储到在线php测试器中,我得到了这个" Undefined offset"错误/警告。
捕获组2,3,4是可选的,所以我做了(?: ( capture ) )?但是php是如此混乱 你 can't even test for undefined group

更新
@hcm - 好的,想通了。这些在线测试人员不会将CRLF翻译成LF 因此,当使用多线模式时,$在换行符或换行符之前是绑定的 ^位于换行符或字符串的开头之后,这没问题。

因此,$仅在LF之前的CR之前不匹配。解决方法可能是使用了 \R任何换行构造,但不是边界,它是一个真实的角色 我所做的就是解决这个问题,就是在断言之外使用(?: $ | (?= \r) ) 内部断言(?: $ | \r )。这可以解决所有问题。

阅读完您的消息后,我已经更改了正则表达式,以便每个部分都是可选的,但是 仍然位置。

4个可选部分如下 1.在郎代码之前。
2.郎代码。
3.郎代码之后。
4.参数。

没有任何部分会跑过另一部分 所有前导/都从每个部分中取出(不是匹配的一部分), 内部斜线留在原位。

剩下的就是按照自己的意愿构建新网址 让我知道这是怎么回事,或者你是否需要进行一些调整。

PHP代码:

// Go to this website:
// http://writecodeonline.com/php/
// Cut & paste this into the code box, hit run.

$text = '
  invalid    
/
/de
/de/coolentry
localhost/
localhost/blogpage
localhost/blogpage/
localhost/blogpage/de/
/localhost/blogpage/coolentry/famous   invalid
/root/blog/page/cool/entry/?entryPage=1&var1=A&var2=B
localhost/blogpage/coolentry/
localhost/blogpage/de/coolentry/
localhost/blogpage/de/coolentry/
localhost/blogpage/de/coolentry/?entryPage=1
localhost/blogpage/coolentry/?entryPage=2
';

$str = preg_replace_callback('~^(?![^\S\r\n]*(?:\r|$))(?|(?!/[a-z]{2}[^\S\r\n]*(?:/|(?:\r|$)))/?((?:(?!/[a-z]{2}[^\S\r\n]*(?:/|(?:\r|$))|\?|/[^\S\r\n]*(?:\r|$))\S)*)|())(?|/([a-z]{2})(?=/|[^\S\r\n]*(?:\r|$))|())(?|/((?:(?!/[^\S\r\n]*(?:\r|$))[^?\s])+)|())(?|/\?((?:(?!/[^\S\r\n]*(?:\r|$))\S)*)|())/?[^\S\r\n]*(?:$|(?=\r))~m',
         function( $matches )
         {
            ///////////////// URL //////////////////
              $url = '';

               // Before lang code -- Group 1
              if ( $matches[1] != '' ) {
                   $url .= '/' . $matches[1];
              }
               // After lang code  -- Group 3
              if ( $matches[3] != '' ) {
                   $url .= '/' . $matches[3];
              }

            ///////////////// PARAMS //////////////////
              $params = '/?lng=';

               // Lang code -- Group 2
              if ( $matches[2] != '' ) {
                   $params .= $matches[2];
              }
              else {
                   $params .= 'en';    // No lang given, set default
              }
               // Other params
              if ( $matches[4] != '') {
                   $params .= '&' . $matches[4];
              }

            ///////////////// Check there is a Url //////////////////
              if ( $url == '' ) {        // No url given, set a default
                   $url = '/language';   // 'language', 'localhost', etc...
              } 

            ///////////////// Put the pieces back together //////////////////
              $NewURL = $url . $params;
              return $NewURL;
         },
         $text);

print $str;

输出:

  invalid    
/language/?lng=en
/language/?lng=de
/coolentry/?lng=de
/localhost/?lng=en
/localhost/blogpage/?lng=en
/localhost/blogpage/?lng=en
/localhost/blogpage/?lng=de
/localhost/blogpage/coolentry/famous  invalid
/root/blog/page/cool/entry/?lng=en&entryPage=1&var1=A&var2=B
/localhost/blogpage/coolentry/?lng=en
/localhost/blogpage/coolentry/?lng=de
/localhost/blogpage/coolentry/?lng=de
/localhost/blogpage/coolentry/?lng=de&entryPage=1
/localhost/blogpage/coolentry/?lng=en&entryPage=2

正则表达式

 # '~^(?![^\S\r\n]*(?:\r|$))(?|(?!/[a-z]{2}[^\S\r\n]*(?:/|(?:\r|$)))/?((?:(?!/[a-z]{2}[^\S\r\n]*(?:/|(?:\r|$))|\?|/[^\S\r\n]*(?:\r|$))\S)*)|())(?|/([a-z]{2})(?=/|[^\S\r\n]*(?:\r|$))|())(?|/((?:(?!/[^\S\r\n]*(?:\r|$))[^?\s])+)|())(?|/\?((?:(?!/[^\S\r\n]*(?:\r|$))\S)*)|())/?[^\S\r\n]*(?:$|(?=\r))~m'

 ^                             # BOL
 (?!                           # Not a blank line, remove to generate a total default url
      [^\S\r\n]* 
      (?: \r | $ )
 )

 (?|                           # BEFORE lang code

      (?!
           / [a-z]{2} [^\S\r\n]*         # not lang code
           (?:
                /
             |  (?: \r | $ )
           )
      )
      /?                            # strip leading '/'
      (                             # (1 start)
           (?:
                (?!
                     / [a-z]{2} [^\S\r\n]*         # not lang code
                     (?:
                          /
                       |  (?: \r | $ )
                     )
                  |  
                     \?                            # not parms
                  |  
                     / [^\S\r\n]*                  # not final slash
                     (?: \r | $ )
                )
                \S 
           )*
      )                             # (1 end)
   |  
      ( )                           # (1)
 )
 (?|                           # LANG CODE
      /                             # strip leading '/'
      ( [a-z]{2} )                  # (2)
      (?=
           /
        |  [^\S\r\n]* 
           (?: \r | $ )
      )
   |  
      ( )                           # (2)
 )

 (?|                           # AFTER lang code
      /                             # strip leading '/'
      (                             # (3 start)
           (?:
                (?!                           # not final slash
                     / [^\S\r\n]* 
                     (?: \r | $ )
                )
                [^?\s]                        # not parms
           )+
      )                             # (3 end)
   |  
      ( )                           # (3)
 )

 (?|                           # PARAMETERS
      / \?                          # strip leading '/?'
      (                             # (4 start)
           (?:
                (?!                           # not final slash
                     / [^\S\r\n]* 
                     (?: \r | $ )
                )
                \S 
           )*
      )                             # (4 end)
   |  
      ( )                           # (4)
 )

 /? 
 [^\S\r\n]*                    # EOL
 (?:
      $ 
   |  (?= \r )
 )