使用PHP中的模式解析URL?

时间:2016-11-20 01:38:03

标签: php regex

如何使用PHP中的regexp或其他内容确定urls匹配某些带有令牌的模式(url => pattern):

  1. node / 11221 =>节点/的%节点
  2. node / 38429 / news =>节点/的%节点 /消息
  3. 相册/ 34234 / shadowbox / 321023 =>相册/的%专辑 /太极拳/的%相片
  4. 提前致谢!

    更新1

    写了下面的脚本:

    <?php
    
    $patterns = [
        "node/%node",
        "node/%node/news",
        "album/%album/shadowbox/%photo",
        "media/photo",
        "blogs",
        "news",
        "node/%node/players",
    ];
    
    $url = "node/11111/news";
    
    foreach ($patterns as $pattern) {
    
        $result_pattern = preg_replace("/\/%[^\/]+/x", '/*', $pattern);
    
        $to_replace = ['/\\\\\*/']; // asterisks
        $replacements = ['[^\/]+'];
    
        $result_pattern = preg_quote($result_pattern, '/');
        $result_pattern = '/^(' . preg_replace($to_replace, $replacements, $result_pattern) . ')$/';
    
        if (preg_match($result_pattern, $url)) {
            echo "<pre>" . $pattern . "</pre>"; 
        }
    
    }
    
    
    ?>
    

    有人能分析一下这段代码是否足够好吗?并且还解释了为什么这一部分中存在如此多的斜杠$to_replace = ['/\\\\\*/'];(关于替换,在互联网上找到了这样的解决方案)。

3 个答案:

答案 0 :(得分:3)

如果您事先知道格式,可以使用preg_match。例如,在第一个示例中,您知道%node只能是数字。匹配的倍数应该像我们之前一样容易,只需将正则表达式存储在数组中:

$patterns = array(
    'node/%node' => '|node/[0-9]+$|',
    'node/%node/news' => '|node/[0-9]+/news|',
    'album/%album/shadowbox/%photo' => '|album/[0-9]+/shadowbox/[0-9]+|',
    'media/photo' => '|media/photo|',
    'blogs' => '|blogs|',
    'news' => '|news|',
    'node/%node/players' => '|node/[0-9]+/players|',

);

$url = "node/11111/players";

foreach ($patterns as $pattern => $regex) {
    preg_match($regex, $url, $results);
    if (!empty($results)) {
        echo "<pre>" . $pattern . "</pre>"; 
    }
}

请注意我是如何将问号$添加到第一条规则的末尾,这样可以确保它不会违反第二条规则。

答案 1 :(得分:2)

以下是上述解决方案的通用解决方案

<?php
    // The url part
    $url     = "/node/123/hello/strText";
    // The pattern part
    $pattern = "/node/:id/hello/:test";

    // Replace all variables with * using regex
    $buffer = preg_replace("(:[a-z]+)", "*", $pattern);
    // Explode to get strings at *
    // In this case ['/node/','/hello/']
    $buffer = explode("*", $buffer);
    // Control variables for loop execution
    $IS_MATCH = True;
    $CAPTURE  = [];
    for ($i=0; $i < sizeof($buffer); $i++) { 
        $slug = $buffer[$i];
        $real_slug = substr($url, 0 , strlen($slug));
        if (!strcmp($slug, $real_slug)) {
            $url = substr($url, strlen($slug));
            $temp = explode("/", $url)[0];
            $CAPTURE[sizeof($CAPTURE)+1] = $temp;
            $url = substr($url,strlen($temp));
        }else {
            $IS_MATCH = False;
        }

    }
    unset($CAPTURE[sizeof($CAPTURE)]);
    if($IS_MATCH)
        print_r($CAPTURE);
    else
        print "Not a match";
?>

您几乎可以将上面的代码转换为函数并传递参数以检查数组大小写。第一步是正则表达式将所有variables转换为*,并将*转换为爆炸。最后循环遍历此数组并继续与url进行比较,以查看模式是否匹配使用简单的字符串比较。

答案 2 :(得分:2)

只要模式已修复,您就可以使用preg_match()功能:

var array = ["2016/11/14", "2016/11/15", "2016/11/16"];

要匹配其他模式,请根据需要进行调整。