这是我的代码:
class Route
{
public function createURL($pattern, array $params = array())
{
$url = $pattern;
if ($params && preg_match_all('#([^/\(\)]*)?#', $pattern, $args)) {
$args = $args[1];
foreach ($params as $value) {
foreach ($args as $key) {
if ($key && preg_match('/'. $key .'/', $value)) {
$url = preg_replace('/'. $key .'/', $value, $url, 1);
}
}
}
}
return $url;
}
}
现在,我称之为方法:
$r = new Route();
$r->createURL('/user/[0-9]+', array(3));
返回结果:'/ user / [3-9] +'
我希望它返回结果:'/ user / 3'
有人可以帮助我吗?
答案 0 :(得分:1)
preg_replace应更改为:
$url = str_replace($key, $value, $url);
preg_replace将[0-9] +视为正则表达式,表示匹配0到9之间的任何数字。
然后你在你的网址中有了它,它被视为一个字符串,所以它匹配网址中的0并用数字替换它。
答案 1 :(得分:0)
你的代码很难调试......
我通过替换:
使其成功$url = preg_replace('/'. $key .'/', $value, $url, 1);
由此:
$url = str_replace($key, $value, $url);
你必须找到一种只替换它的方法。
这样的事情:
$pieces = explode($key);
$pieces[1] .= $pieces[0].$value;
$url = implode($key, $pieces);
MAY 为你工作!
Disclainer:虽然Antony D'Andrea说它首先使用str_replace
,但我提供了另一种方法。我没有读过他的答案,也没有注意到它的内容。
Offtopic:
我已经使用了你的精彩想法并将其重写为:
class Route
{
static function createURL($pattern, array $params = array())
{
$func = function($matches) use ($params) {
if (preg_match('@^([a-z]+):(.*)$@', $matches[1], $patterns) && preg_match('@^'.$patterns[2].'$@', $params[$patterns[1]]) )
return $params[$patterns[1]];
else return '';
};
return preg_replace_callback('@%\\[([a-z]+:(?:[^]]|\\][^%])*)\\]%@', $func, $pattern);
}
}
echo Route::createURL('/users/%[id:\d+]%/',array('id'=>5));
它按预期工作,但暂时不能在模式中使用 []
。
使用正则表达式@%\\[([a-z]+:(?:[^]]|\\][^%])*)\\]%@
代替@%\\[([a-z]+:(?:[^]]|\\\])*)\\]%@
似乎可以克服这一点。
为了使编码更容易,我决定做一些与你不同的事情。
它会查找%[ ... ]%
之间的内容,并期望内部有key:pattern
。
然后,在您的阵列上,您提供与该键匹配的值。如果未找到或模式与值不匹配,请尝试将其删除。
使用preg_replace_callback()
的方法的优势在于您可以按照自己的方式处理匹配,并且可以确保只更换一次。