Php 使用正则表达式将URL与模式匹配,返回一个键数组

Php 使用正则表达式将URL与模式匹配,返回一个键数组,php,regex,Php,Regex,我正在用PHP组装一个路由器,它将一个模式(如“users/:id”)与一个路由(如“users/123”)相匹配,返回类似“id”=>123的内容。这就是我目前所拥有的 function match_path($path, $pattern){ if ($path == $pattern){ return true; } // check for :replacements if (strpos($pattern, ":")!== false) { // split path &

我正在用PHP组装一个路由器,它将一个模式(如“users/:id”)与一个路由(如“users/123”)相匹配,返回类似“id”=>123的内容。这就是我目前所拥有的

function match_path($path, $pattern){
if ($path == $pattern){
  return true;
}
// check for :replacements
if (strpos($pattern, ":")!== false) {
  // split path & pattern into fragments
  $split_path =  explode('/',$path);
  $split_pattern = explode('/', $pattern);
  // check that they are the same length
  if (count($split_path) !== count($split_pattern)){
    return false;
  }
  // iterate over pattern
  foreach ($split_pattern as $index => $fragment) {
    // if fragment is wild
    if (strpos($fragment, ":") == 0){
      $params[substr($fragment, 1)] = $split_path[$index];
    // if fragment doesn't match
    } elseif ($fragment !== $split_path[$index]) {
      return false;
    }
    // continue if pattern matches
  }
  // returns hash of extracted parameters
  return $params;
}
return false;

}
我确信一定有一种方法可以用正则表达式干净地实现这一点

更好的是,可能有一个PHP函数可以实现这一点。

PHP on Rails,嗯?;-)

有关strpos行为的重要注意事项:您应该使用strict
==
运算符进行检查,因为它可能返回false(来源: ).经过粗略的阅读/测试,我只看到脚本有问题

<?php
// routes-test.php

echo "should be [ id => 123 ]:\n";
var_dump( match_path( 'user/123', 'user/:id' ) );

function match_path($path, $pattern) { ... }
?>

// cmd line
$ php routes-test.php # your implementation
should be [ id => 123 ]:
array(2) {
  ["ser"]=>
  string(4) "user"
  ["id"]=>
  string(3) "123"
}
$ php routes-test.php # using ===
should be [ id => 123 ]:
array(1) {
  ["id"]=>
  string(3) "123"
}

//命令行
$php routes-test.php#您的实现
应该是[id=>123]:
阵列(2){
[“ser”]=>
字符串(4)“用户”
[“id”]=>
字符串(3)“123”
}
$php routes-test.php#使用===
应该是[id=>123]:
阵列(1){
[“id”]=>
字符串(3)“123”
}

您应该采用YAGNI方法来使用正则表达式。如果你所要做的就是匹配像
/^:\w+$/
这样的东西,那么你可以更快地完成它,并且在与strpo和朋友相当数量的行中完成。

使用这样的东西怎么样

/**
 * Compares a url to a pattern, and populates any embedded variables
 * Returns false if the pattern does not match
 * Returns an array containing the placeholder values if the pattern matches
 * If the pattern matches but does not contain placeholders, returns an empty array
 */
function checkUrlAgainstPattern($url, $pattern) {
    // parse $pattern into a regex, and build a list of variable names
    $vars = array();
    $regex = preg_replace_callback(
        '#/:([a-z]+)(?=/|$)#',
        function($x) use (&$vars) {
            $vars[] = $x[1];
            return '/([^/]+)';
        },
        $pattern
    );

    // check $url against the regex, and populate variables if it matches
    $vals = array();
    if (preg_match("#^{$regex}$#", $url, $x)) {
        foreach ($vars as $id => $var) {
            $vals[$var] = $x[$id + 1];
        }
        return $vals;
    } else {
        return false;
    }
}
这用于将模式转换为正则表达式并捕获占位符列表,然后根据生成的正则表达式计算url并提取占位符值

一些用法示例:

checkUrlAgainstPattern('/users/123', '/users/:id');
// returns array('id' => '123')

checkUrlAgainstPattern('/users/123/123', '/users/:id');
// returns false

checkUrlAgainstPattern('/users/123/details', '/users/:id/:page');
// returns array('id' => '123', 'page' => 'details')

我不确定你打算用它做什么,但是
.htaccess
甚至可能是可能的,这通常用于奇特的url'看起来他正试图在应用程序级别实现路由
.htaccess
速度更快,但从开发角度来看,灵活性较差。