Your code is really hard to debug...
I've made it to work by replacing:
$url = preg_replace('/'. $key .'/', $value, $url, 1);
by this:
$url = str_replace($key, $value, $url);
You will have to find a way to only replace it once.
Something like this:
$pieces = explode($key);
$pieces[1] .= $pieces[0].$value;
$url = implode($key, $pieces);
MAY work for you!
Disclainer: Although Antony D'Andrea said it first to use the str_replace
, I've provided an alternative method. I didn't read his answer and didn't paid attention to it's content.
Offtopic:
I've used your brilliant idea and rewrote it like this:
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));
It's working as intended, but you can't use []
inside the pattern, for now.
Using the regex @%\\[([a-z]+:(?:[^]]|\\][^%])*)\\]%@
instead of @%\\[([a-z]+:(?:[^]]|\\\])*)\\]%@
seems to overcome this.
To make the coding easier, I've decided to do something different than you.
It looks for something between %[ ... ]%
, and expects something like key:pattern
inside.
Then, on your array, you provide a value matching that key. If none is found or the pattern doesn't match the value, tries to remove it.
The aproach using preg_replace_callback()
has the advantage of allowing you to process the match the way you wish and you can be sure that you are replacing it only once.