我正在将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函数可以做到这一点。
答案 0 :(得分:1)
PHP on Rails,是吗? ; - )
有关strpos
的行为的重要说明:,您应该使用严格 ===
运算符进行检查,因为它可能会返回false(来源: http://php.net/manual/en/function.strpos.php
)。在粗略阅读/测试之后,这是我对脚本的错误......
<?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"
}
你应该采用YAGNI方法来使用正则表达式。如果您所做的只是匹配/^:\w+$/
之类的东西,那么您可以更快地完成它并且与strpos和朋友在相同数量的行中。
答案 1 :(得分:0)
如何使用这样的东西?
/**
* 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;
}
}
这使用preg_replace_callback()
将模式转换为正则表达式并捕获占位符列表,然后preg_match()
根据生成的正则表达式计算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')