我已经编写了一个PHP控制器,但我正在重写我的代码,所以我可以使用类似Backbone路由器的JSON路由将URI模式映射到PHP Class ::方法组合,或者直接传递给HTML文档然后传递对客户来说,就像这样:
{
"/home" : "index.html",
"/podcasts": "podcasts.html",
"/podcasts/:param1/:param2": "SomeClass::someMethod"
}
Backbone动态创建正则表达式以匹配URL的路由。我查看了主干代码,并提取了以下代码(它有点修改):
function _routeToRegExp (route) {
var optionalParam = /\((.*?)\)/g;
var namedParam = /(\(\?)?:\w+/g;
var splatParam = /\*\w+/g;
var escapeRegExp = /[\-{}\[\]+?.,\\\^$|#\s]/g;
route = route.replace(escapeRegExp, '\\$&')
.replace(optionalParam, '(?:$1)?')
.replace(namedParam, function(match, optional){
return optional ? match : '([^\/]+)';
})
.replace(splatParam, '(.*?)');
return new RegExp('^' + route + '$');
}
当我将/podcasts/:param1/:param2
之类的路线传递给上面的代码时,我得到了/^\/podcasts\/([^\/]+)\/([^\/]+)$/
。我试图编写一个PHP函数来获得完全相同的正则表达式。我试过了:
$route = '/podcasts/:param1/:param2';
$a = preg_replace('/[\-{}\[\]+?.,\\\^$|#\s]/', '\\$&', $route); // escapeRegExp
$b = preg_replace('/\((.*?)\)/', '(?:$1)?', $a); // optionalParam
$c = preg_replace('/(\(\?)?:\w+/', '([^\/]+)', $b); // namedParam
$d = preg_replace('/\*\w+/', '(.*?)', $c); // splatParam
$pattern = "/^{$d}$/";
echo "/^\/podcasts\/([^\/]+)\/([^\/]+)$/\n";
echo "{$pattern}\n";
$matches = array();
preg_match_all($pattern, '/podcasts/param1/param2', $matches);
print_r($matches);
我的输出是:
/^\/podcasts\/([^\/]+)\/([^\/]+)$/ // The expected pattern
/^/podcasts/([^\/]+)/([^\/]+)$/ // echo "{$pattern}\n";
Array // print_r($matches);
(
)
为什么我的正则表达式输出不同?我可以处理剩下的映射过程和所有,但我还没有弄清楚如何在PHP中获得与Javascript完全相同的正则表达式。有什么建议吗?
答案 0 :(得分:2)
JS版本实际上并没有转义/ chars,它产生与PHP版本/podcasts/([^/]+)/([^/]+)
相同的字符串表示形式,但是,这可能是你绊倒的一个,console.log
返回的正则表达式_routeToRegExp
显示带有分隔符的完整表示形式,并且内部的表示已转义:
//Firefox output
RegExp /^\/podcasts\/([^\/]+)\/([^\/]+)$/
请参阅http://jsfiddle.net/w6zP2/了解演示。
评论中提到的@ajshort以及Backbone所做的是同一解决方案:跳过/转义并使用替代语法; Backbone通过使用new RegExp('^' + route + '$')
显式调用Regexp构造函数来执行此操作,您可以使用$pattern = "~^{$d}$~";
PHP小提琴http://phpfiddle.org/main/code/4de-jf3似乎按预期工作。
请注意,在替换字符串中的Javascript $&
中,插入匹配的子字符串 1 ,而在PHP 2 中则不然。应修改escapeRegExp,可能如下所示:
$a = preg_replace('/[\-{}\[\]+?.,\\\^$|#~\s]/', '\\\\$0', $route);
为我们提供了更新的代码:
$a = preg_replace('/[\-{}\[\]+?.,\\\^$|#~\s]/', '\\\\$0', $route); // escapeRegExp
$b = preg_replace('/\((.*?)\)/', '(?:$1)?', $a); // optionalParam
$c = preg_replace('/(\(\?)?:\w+/', '([^\/]+)', $b); // namedParam
$d = preg_replace('/\*\w+/', '(.*?)', $c); // splatParam
$pattern = "~^{$d}$~";
echo "/^\/podcasts\/([^\/]+)\/([^\/]+)$/\n";
echo "{$pattern}\n";
$matches = array();
preg_match_all($pattern, '/podcasts/param1/param2', $matches);
print_r($matches);
1 在string.replace中查看将字符串指定为参数 2 请参阅preg_replace
中的替换